Flex-table-card

Not entirely sure what you mean - but this is one of the sensors returned:

I think in the context of the friendly_name, it comes back as text - however now under 2025.5.2 it works fine, so no idea.

I was playing around and have since added region_name to the attributes generated.

I suspect it was the data that changed and not the version of HA. If it happens again, check the “friendly_name” values of all of the sensors. You will likely find one that is not a Javascript string, and therefore won’t have a “replace” method. You can test for that condition in your “modify” statement with:

typeof x !== “string”

and avoid the error.

1 Like

Thanks, will keep that in mind if it does it again.

Reverting to 2025.4.x fixed it at the time too, so didn’t think that the data was the issue, but also didn’t spend much time on it.

Hi @Ildar_Gabdullin and @Biscuit

I followed your approach of storing an array inside a single attribute of one sensor, in order to display some JSON data. It works nicely. Here is my sensor:

and here is my flex-table configuration:

However, I am not able to format the numbers in the columns. For example, do you know if there’s a simple way to format one of the columns to 2 decimal places? I have tried using something like this, but it’s not outputting anything:

  - name: Initial SOC
    data: data
    modify: >
      return parseFloat(x.initial_soc).toFixed(2);

I’m doing this in my table:

type: custom:flex-table-card
columns:
  - data: json
    modify: x.entity_id
    name: Entity ID
  - data: json
    modify: x.count
    name: events/day
  - data: json
    modify: (x.count/24).toFixed(2)
    name: events/h
entities:
  include: sensor.recorder_top_events

Thanks for this - you are right, this works:

type: custom:flex-table-card
title: Most Recent Charging Sessions
entities:
  - sensor.charging_sessions_last_n_rows
data_path: data
columns:
  - name: Session Start
    data: data
    modify: "new Date(x.session_start.replace(' ', 'T')).getFullYear();"
  - name: Session End
    data: data
    modify: "new Date(x.session_start.replace(' ', 'T')).getMonth();"
  - name: Initial SOC
    data: data
    modify: (x.initial_soc).toFixed(0)
    suffix: " %"

For some reason, we don’t use the “return” syntax, like with regular javascript expressions…

Cheers

For example, I have my first two columns which contain strings for initial time and final time. I would like a new column which displays the difference between them in the format like “7h 8m”. But something like this results in an error:

type: custom:flex-table-card
title: Charging Sessions
entities:
  - sensor.charging_sessions_last_n_rows
columns:
  - name: Session Start
    data: data
    modify: x.session_start
  - name: Session End
    data: data
    modify: x.session_end
  - name: Hours
    data: data
    modify: >
      const start = new Date(x.session_start.replace(' ', 'T'));
      const end = new Date(x.session_end.replace(' ', 'T'));
      const diffInMinutes = Math.round((end - start) / 60000);
      const hours = Math.floor(diffInMinutes / 60);
      const minutes = diffInMinutes % 60;
      return `${hours}h ${minutes}m`;

I can’t see a way to do it…

    modify: |-
      const p=(new Date(x.upto) - new Date(x.from))/60000;
      const hours = Math.floor(p / 60);
      const minutes = p % 60;
      `${hours}h ${minutes}m`

It is not a function, it uses eval, and the end result is the last line of JS

Change the x.upto etc to suit your needs

Hi all,

I have a working table that pulls in the upcoming MLB games and shows the starting pitcher match-ups. It works great for days where only one game is being played. On days where there is a double header (like today), I am only retrieving the first game.

What I’m trying to solve is showing both games of a single day when a double header exists.

My dashboard code is only grabbing the x.games[0] location, but I can’t seem to figure out how to make it work any other way.

Any thoughts on how to show both games of a double header?

Dashboard code which shows game 1 of a day:

views:
  - title: Braves Schedule
    type: panel
    cards:
      - type: vertical-stack
        cards:
          - type: markdown
            title: null
            content: |
              <h2>Probable Pitchers for upcoming games</h2>
          - type: custom:flex-table-card
            title: null
            css:
              table+: >-
                padding: 8px;  width: 100%;  max-width: 1600px;  display: block;
                overflow-x: auto; text-align: center;
              tbody tr td:first-child: >-
                min-width: 60px; text-align: center; padding: 8px; white-space:
                nowrap;
              tbody tr td:nth-child(2): >-
                min-width: 80px; text-align: center; padding: 8px; white-space:
                nowrap;
              tbody tr td:nth-child(3): >-
                width: auto; text-align: left; white-space: nowrap; padding:
                8px;
              tbody tr td:nth-child(n+4): >-
                width: auto; text-align: center; white-space: nowrap; padding:
                8px;
              tbody tr td:nth-child(n+5): 'width: auto; text-align: center; padding: 8px;'
              th:nth-child(1): 'text-align: center; white-space: nowrap;'
              th:nth-child(2): 'text-align: center; white-space: nowrap;'
              th:nth-child(6): 'text-align: center; white-space: nowrap;'
              th:nth-child(7): 'text-align: center; white-space: nowrap;'
              th:nth-child(8): 'text-align: center; white-space: nowrap;'
              th:nth-child(9): 'text-align: center; white-space: nowrap;'
              th:nth-child(10): 'text-align: center; white-space: nowrap;'
              th:nth-child(11): 'text-align: center; white-space: nowrap;'
              th:nth-child(12): 'text-align: center; white-space: nowrap;'
              th:nth-child(13): 'text-align: center; white-space: nowrap;'
              th:nth-child(14): 'text-align: center; white-space: nowrap;'
              '@media (max-width: 600px)': |
                tbody tr td {
                  font-size: 12px;
                  padding: 2px;
                }
                tbody tr td img {
                  width: 15px;
                  height: 15px;
                }
                table {
                  width: 100%;
                }
                tbody tr td:nth-child(2) {
                  white-space: nowrap; /* Prevent wrapping in the Game column */
                  overflow: hidden;
                  text-overflow: ellipsis;  /* Adds ellipsis for overflow */
                }
                tbody tr td:nth-child(3) {
                  white-space: nowrap; /* Prevent wrapping in the Details column */
                  overflow: hidden;
                  text-overflow: ellipsis;  /* Adds ellipsis for overflow */
                }
            entities:
              include: sensor.mlb_braves_schedule
            max_rows: 5
            columns:
              - name: Time
                data: dates
                modify: >
                  new Date(x.games[0].gameDate).toLocaleDateString('en-US', {
                      weekday: 'short',
                      month: 'numeric',
                      day: 'numeric'
                  }).replace(',', '') + '<br>' + new
                  Date(x.games[0].gameDate).toLocaleTimeString('en-US', {
                      hour: 'numeric',
                      minute: '2-digit',
                      hour12: true,
                      timeZone: 'America/New_York'
                  })
              - name: Game
                data: dates
                modify: >-
                  `${x.games[0].status.statusCode === 'P' ||
                  x.games[0].status.statusCode === 'S' ? 
                      `<img src="https://www.mlbstatic.com/team-logos/team-cap-on-dark/${x.games[0].teams.away?.team?.id}.svg" 
                       style="width: 20px; height: 20px; vertical-align: middle; margin-right: 5px;">
                       ${x.games[0].teams.away?.team?.abbreviation || 'N/A'}
                       <span style="font-size: 12px; color: gray;">
                         (${x.games[0].teams.away?.leagueRecord?.wins || '0'}-${x.games[0].teams.away?.leagueRecord?.losses || '0'})
                       </span><br>
                       <img src="https://www.mlbstatic.com/team-logos/team-cap-on-dark/${x.games[0].teams.home?.team?.id}.svg" 
                       style="width: 20px; height: 20px; vertical-align: middle; margin-right: 5px;">
                       ${x.games[0].teams.home?.team?.abbreviation || 'N/A'}
                       <span style="font-size: 12px; color: gray;">
                         (${x.games[0].teams.home?.leagueRecord?.wins || '0'}-${x.games[0].teams.home?.leagueRecord?.losses || '0'})
                       </span>`
                       : ''}`
              - name: Probable Pitchers
                data: dates
                modify: |-
                  `${x.games[0].teams.away.probablePitcher ? 
                    `<a href="https://www.mlb.com/player/${x.games[0].teams.away.probablePitcher.nameSlug}" target="_blank">
                      <img src="https://midfield.mlbstatic.com/v1/people/${x.games[0].teams.away.probablePitcher.id}/silo/60?zoom=1.2" 
                           style="width:20px; height:20px; border-radius:50%; margin-right:5px;"></a>` 
                    : ''} 
                    ${x.games[0].teams.away.probablePitcher ? x.games[0].teams.away.probablePitcher.lastName : 'TBD'}
                    ${x.games[0].teams.away.probablePitcher && x.games[0].teams.away.probablePitcher.stats && x.games[0].teams.away.probablePitcher.stats[3] ? 
                    '(' + x.games[0].teams.away.probablePitcher.stats[3].stats.summary + ')' : ''} <br>
                   ${x.games[0].teams.home.probablePitcher ? 
                    `<a href="https://www.mlb.com/player/${x.games[0].teams.home.probablePitcher.nameSlug}" target="_blank">
                      <img src="https://midfield.mlbstatic.com/v1/people/${x.games[0].teams.home.probablePitcher.id}/silo/60?zoom=1.2" 
                           style="width:20px; height:20px; border-radius:50%; margin-right:5px;"></a>` 
                    : ''} 
                    ${x.games[0].teams.home.probablePitcher ? x.games[0].teams.home.probablePitcher.lastName : 'TBD'}
                    ${x.games[0].teams.home.probablePitcher && x.games[0].teams.home.probablePitcher.stats && x.games[0].teams.home.probablePitcher.stats[3] ? 
                    '(' + x.games[0].teams.home.probablePitcher.stats[3].stats.summary + ')' : ''}`

                   
              - name: Age
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher ?
                  x.games[0].teams.away.probablePitcher.currentAge : '-'}<br>
                  ${x.games[0].teams.home.probablePitcher ?
                  x.games[0].teams.home.probablePitcher.currentAge : '-'} `
              - name: Hand
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher ?
                  (x.games[0].teams.away.probablePitcher.pitchHand.code === 'R'
                  ? 'RHP' : 'LHP') : '-'}<br>
                  ${x.games[0].teams.home.probablePitcher ?
                  (x.games[0].teams.home.probablePitcher.pitchHand.code === 'R'
                  ? 'RHP' : 'LHP') : '-'} `
              - name: K
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.strikeOuts
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.strikeOuts
                  : '-'} `
              - name: WHIP
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.whip :
                  '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.whip :
                  '-'} `
              - name: Strike %
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.strikePercentage
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.strikePercentage
                  : '-'} `
              - name: Pitch/Inn
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.pitchesPerInning
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.pitchesPerInning
                  : '-'} `
              - name: K/BB
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.strikeoutWalkRatio
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.strikeoutWalkRatio
                  : '-'} `
              - name: K/9
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.strikeoutsPer9Inn
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.strikeoutsPer9Inn
                  : '-'} `
              - name: BB/9
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.walksPer9Inn
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.walksPer9Inn
                  : '-'} `
              - name: Hits/9
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher &&
                  x.games[0].teams.away.probablePitcher.stats &&
                  x.games[0].teams.away.probablePitcher.stats[3] ?
                  x.games[0].teams.away.probablePitcher.stats[3].stats.hitsPer9Inn
                  : '-'}<br> ${x.games[0].teams.home.probablePitcher &&
                  x.games[0].teams.home.probablePitcher.stats &&
                  x.games[0].teams.home.probablePitcher.stats[3] ?
                  x.games[0].teams.home.probablePitcher.stats[3].stats.hitsPer9Inn
                  : '-'} `
              - name: Debut
                data: dates
                modify: >-
                  `${x.games[0].teams.away.probablePitcher ? (new
                  Date(x.games[0].teams.away.probablePitcher.mlbDebutDate +
                  'T00:00:00').toLocaleDateString('en-US', {
                    month: 'numeric',
                    day: 'numeric',
                    year: 'numeric'
                  })) : '-'}<br> ${x.games[0].teams.home.probablePitcher ? (new
                  Date(x.games[0].teams.home.probablePitcher.mlbDebutDate +
                  'T00:00:00').toLocaleDateString('en-US', {
                    month: 'numeric',
                    day: 'numeric',
                    year: 'numeric'
                  })) : '-'} `

which correctly outputs the first game only:

Here’s the sensor’s attributes that I’m referencing – where two games exist for today:

dates:
  - totalGames: 2
    games:
      - gamePk: 777735
        gameDate: "2025-05-29T17:05:00Z"
        status:
          statusCode: S
        teams:
          away:
            leagueRecord:
              wins: 25
              losses: 28
              pct: ".472"
            team:
              id: 144
              name: Atlanta Braves
              venue:
                id: 4705
                name: Truist Park
              abbreviation: ATL
              franchiseName: Atlanta
              clubName: Braves
            probablePitcher:
              id: 700363
              fullName: AJ Smith-Shawver
              firstName: AJ
              lastName: Smith-Shawver
              primaryNumber: "32"
              currentAge: 22
              primaryPosition:
                code: "1"
                name: Pitcher
                type: Pitcher
                abbreviation: P
              boxscoreName: Smith-Shawver
              stats:
                - type:
                    displayName: gameLog
                  group:
                    displayName: hitting
                  stats: {}
                - type:
                    displayName: gameLog
                  group:
                    displayName: pitching
                  stats: {}
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: hitting
                  stats:
                    summary: .000 AVG, 0 HR, 0 RBI
                    strikeOuts: 0
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: pitching
                  stats:
                    summary: 3-2 | 3.67 ERA
                    strikeOuts: 41
                    wins: 3
                    losses: 2
                    whip: "1.42"
                    strikePercentage: ".630"
                    pitchesPerInning: "16.15"
                    strikeoutWalkRatio: "2.05"
                    strikeoutsPer9Inn: "8.86"
                    walksPer9Inn: "4.32"
                    hitsPer9Inn: "8.42"
                    runsScoredPer9: "3.89"
              mlbDebutDate: "2023-06-04"
              pitchHand:
                code: R
              nameSlug: aj-smith-shawver-700363
          home:
            leagueRecord:
              wins: 35
              losses: 19
              pct: ".648"
            team:
              id: 143
              name: Philadelphia Phillies
              venue:
                id: 2681
                name: Citizens Bank Park
              abbreviation: PHI
              franchiseName: Philadelphia
              clubName: Phillies
            probablePitcher:
              id: 650911
              fullName: Cristopher Sánchez
              firstName: Cristopher
              lastName: Sánchez
              primaryNumber: "61"
              currentAge: 28
              primaryPosition:
                code: "1"
                name: Pitcher
                type: Pitcher
                abbreviation: P
              boxscoreName: Sánchez, C
              stats:
                - type:
                    displayName: gameLog
                  group:
                    displayName: hitting
                  stats: {}
                - type:
                    displayName: gameLog
                  group:
                    displayName: pitching
                  stats: {}
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: hitting
                  stats:
                    summary: .000 AVG, 0 HR, 0 RBI
                    strikeOuts: 0
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: pitching
                  stats:
                    summary: 4-1 | 3.17 ERA
                    strikeOuts: 65
                    wins: 4
                    losses: 1
                    whip: "1.26"
                    strikePercentage: ".630"
                    pitchesPerInning: "16.17"
                    strikeoutWalkRatio: "3.25"
                    strikeoutsPer9Inn: "10.83"
                    walksPer9Inn: "3.33"
                    hitsPer9Inn: "8.00"
                    runsScoredPer9: "3.50"
              mlbDebutDate: "2021-06-06"
              pitchHand:
                code: L
              nameSlug: cristopher-sanchez-650911
        venue:
          id: 2681
          name: Citizens Bank Park
        broadcasts:
          - id: 140
            name: NBCSP
            type: TV
            language: en
            callSign: NBCSP
            homeAway: home
          - id: 6220
            name: FanDuel Sports Network South
            type: TV
            language: en
            callSign: FDSNSO
            homeAway: away
          - id: 6221
            name: FanDuel Sports Network Southeast
            type: TV
            language: en
            callSign: FDSNSE
            homeAway: away
          - id: 349
            name: 94 WIP
            type: FM
            language: en
            callSign: WIP
            homeAway: home
          - id: 4024
            name: 680 AM/93.7 FM The Fan
            type: AM
            language: en
            callSign: 680 AM
            homeAway: away
          - id: 5215
            name: MLBN (out-of-market only)
            type: TV
            language: en
            callSign: MLBN
            homeAway: away
          - id: 5215
            name: MLBN (out-of-market only)
            type: TV
            language: en
            callSign: MLBN
            homeAway: home
          - id: 4704
            name: WTTM 1680
            type: AM
            language: es
            callSign: WTTM1680
            homeAway: home
        dayNight: day
        lineups: {}
      - gamePk: 777723
        gameDate: "2025-05-29T22:45:00Z"
        status:
          statusCode: S
        teams:
          away:
            leagueRecord:
              wins: 25
              losses: 28
              pct: ".472"
            team:
              id: 144
              name: Atlanta Braves
              venue:
                id: 4705
                name: Truist Park
              abbreviation: ATL
              franchiseName: Atlanta
              clubName: Braves
            probablePitcher:
              id: 519242
              fullName: Chris Sale
              firstName: Christopher
              lastName: Sale
              primaryNumber: "51"
              currentAge: 36
              primaryPosition:
                code: "1"
                name: Pitcher
                type: Pitcher
                abbreviation: P
              boxscoreName: Sale
              stats:
                - type:
                    displayName: gameLog
                  group:
                    displayName: hitting
                  stats: {}
                - type:
                    displayName: gameLog
                  group:
                    displayName: pitching
                  stats: {}
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: hitting
                  stats:
                    summary: .000 AVG, 0 HR, 0 RBI
                    strikeOuts: 0
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: pitching
                  stats:
                    summary: 2-3 | 3.36 ERA
                    strikeOuts: 78
                    wins: 2
                    losses: 3
                    whip: "1.28"
                    strikePercentage: ".670"
                    pitchesPerInning: "17.22"
                    strikeoutWalkRatio: "4.88"
                    strikeoutsPer9Inn: "11.38"
                    walksPer9Inn: "2.34"
                    hitsPer9Inn: "9.19"
                    runsScoredPer9: "3.65"
              mlbDebutDate: "2010-08-06"
              pitchHand:
                code: L
              nameSlug: chris-sale-519242
          home:
            leagueRecord:
              wins: 35
              losses: 19
              pct: ".648"
            team:
              id: 143
              name: Philadelphia Phillies
              venue:
                id: 2681
                name: Citizens Bank Park
              abbreviation: PHI
              franchiseName: Philadelphia
              clubName: Phillies
            probablePitcher:
              id: 554430
              fullName: Zack Wheeler
              firstName: Zachary
              lastName: Wheeler
              primaryNumber: "45"
              currentAge: 34
              primaryPosition:
                code: "1"
                name: Pitcher
                type: Pitcher
                abbreviation: P
              boxscoreName: Wheeler
              stats:
                - type:
                    displayName: gameLog
                  group:
                    displayName: hitting
                  stats: {}
                - type:
                    displayName: gameLog
                  group:
                    displayName: pitching
                  stats: {}
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: hitting
                  stats:
                    summary: .000 AVG, 0 HR, 0 RBI
                    strikeOuts: 0
                - type:
                    displayName: statsSingleSeason
                  group:
                    displayName: pitching
                  stats:
                    summary: 6-1 | 2.42 ERA
                    strikeOuts: 88
                    wins: 6
                    losses: 1
                    whip: "0.88"
                    strikePercentage: ".660"
                    pitchesPerInning: "15.37"
                    strikeoutWalkRatio: "6.29"
                    strikeoutsPer9Inn: "11.21"
                    walksPer9Inn: "1.78"
                    hitsPer9Inn: "6.11"
                    runsScoredPer9: "2.42"
              mlbDebutDate: "2013-06-18"
              pitchHand:
                code: R
              nameSlug: zack-wheeler-554430
        venue:
          id: 2681
          name: Citizens Bank Park
        broadcasts:
          - id: 6220
            name: FanDuel Sports Network South
            type: TV
            language: en
            callSign: FDSNSO
            homeAway: away
          - id: 140
            name: NBCSP
            type: TV
            language: en
            callSign: NBCSP
            homeAway: home
          - id: 4024
            name: 680 AM/93.7 FM The Fan
            type: AM
            language: en
            callSign: 680 AM
            homeAway: away
          - id: 6221
            name: FanDuel Sports Network Southeast
            type: TV
            language: en
            callSign: FDSNSE
            homeAway: away
          - id: 349
            name: 94 WIP
            type: FM
            language: en
            callSign: WIP
            homeAway: home
          - id: 2661
            name: MLBN
            type: TV
            language: en
            callSign: MLBN
            homeAway: away
          - id: 2661
            name: MLBN
            type: TV
            language: en
            callSign: MLBN
            homeAway: home
          - id: 4704
            name: WTTM 1680
            type: AM
            language: es
            callSign: WTTM1680
            homeAway: home
        dayNight: night
        lineups: {}
  - totalGames: 1
    games:
      - gamePk: 777719
        gameDate: "2025-05-30T23:15:00Z"

What happens if you take away [0] ?

Also, off topic but what are you using to get this data? I like it.

(Go Phils)

If I take away the [0], it breaks and I just get invalid dates – basically the flex table card doesn’t reference the data correctly. The issue is that there’s a nested set of games inside each day and the flex table card is iterating over days, and not inside each day.

As for the aside, I’m pulling this straight from the mlb api using this rest sensor:

##
## MLB Braves Schedule
##
- platform: rest
  name: MLB Braves Schedule
  unique_id: sensor.mlb_braves_schedule
  resource_template: >-
    {% set current_year = now().year %}
    {% set current_month = now().month %}
    {% set current_day = now().day %}
    {% if states('sensor.mlb_season') == 'offseason' %}
      {% set current_year = current_year + 1 %}
      {% set current_month = 1 %}
      {% set current_day = 1 %}
    {% endif %}
    https://statsapi.mlb.com/api/v1/schedule?hydrate=team,stats,broadcasts,person,probablePitcher,lineups&fields=totalGames,dates,games,gamePk,status,statusCode,teams,away,team,id,home,lineups,homePlayers,fullName,firstName,lastName,primaryPosition,abbreviation,awayPlayers,gameDate,leagueRecord,wins,losses,pct,teams,franchiseName,clubName,probablePitcher,fullName,firstName,lastName,primaryNumber,currentAge,boxscoreName,stats,type,displayName,group,summary,strikeOuts,whip,strikePercentage,pitchesPerInning,strikeoutWalkRatio,strikeoutsPer9Inn,walksPer9Inn,runsScoredPer9,hitsPer9Inn,mlbDebutDate,pitchHand,code,broadcasts,name,type,language,homeAway,callSign,dayNight,venue,name,nameSlug&sportId=1&teamId=144&startDate={{ current_month }}/{{ current_day }}/{{ current_year }}&endDate=12/31/{{ current_year }}
  method: GET
  value_template: "{{ value_json.totalGames }}"
  json_attributes:
    - dates
  scan_interval: 86400 # Updates once per day

The braves are ‘teamID=144’ which I’ve hardcoded into the statsapi URL, you’d use ‘teamID=143’ for the Phils.

The [0] only grabs the first one. If you change it to [1], you will get the second one.

You can check the count and grab the second one if it exists.

Agreed, but I cant figure out how to show both the [0] and the [1] iterations…since both games were active today.

Been a busy day. Have not had a chance to dig in.

Will try tonight. I expect you will need to pre process the data and get each game into their own full record at position 0 or something like that.

I converted your rest sensor to a command_line sensor and then used jq to change the structure of the response. I also limited it to 7 days because HA does not like the length of the response for the full season.

command_line:
  - sensor:
      name: MLB Phillies Schedule
      unique_id: mlb_phillies_schedule
      command: >-
        curl
        {% set start_date = (now().strftime('%m/%d/%Y'))[1:] %}
        {% set end_date = (now() + timedelta(days=7)).strftime('%m/%d/%Y')[1:] %}
        -s -L 'https://statsapi.mlb.com/api/v1/schedule?hydrate=team,stats,broadcasts,person,probablePitcher,lineups&fields=totalGames,dates,games,gamePk,status,statusCode,teams,away,team,id,home,lineups,homePlayers,fullName,firstName,lastName,primaryPosition,abbreviation,awayPlayers,gameDate,leagueRecord,wins,losses,pct,teams,franchiseName,clubName,probablePitcher,fullName,firstName,lastName,primaryNumber,currentAge,boxscoreName,stats,type,displayName,group,summary,strikeOuts,whip,strikePercentage,pitchesPerInning,strikeoutWalkRatio,strikeoutsPer9Inn,walksPer9Inn,runsScoredPer9,hitsPer9Inn,mlbDebutDate,pitchHand,code,broadcasts,name,type,language,homeAway,callSign,dayNight,venue,name,nameSlug&sportId=1&teamId=143&startDate={{ start_date }}&endDate={{ end_date }}' | jq '{ "games_list": [ .dates | .[] | .games | .[] ] }'

      scan_interval: 86400
      value_template: "{{ value_json.games_list | length if value_json and value_json.games_list is iterable else 0 }}"
      json_attributes:
        - games_list

You may want to use your date template again. I don’t know if this is a bug or expected behavior, but I needed to start the command with curl and then insert the template before continuing with the rest of the command. Otherwise, HA was trying to use the first line of the template in the command. :man_shrugging:

Here’s my flex-table-card result. I’m not using all the data you are, but if you use games_list for your data, you should just need to remove games[0]. from your modify code.

type: custom:flex-table-card
title: Phillies Upcoming Games
entities:
  include: sensor.mlb_phillies_schedule
columns:
  - name: Date
    data: games_list
    modify: |-
      new Date(x.gameDate).toLocaleDateString('en-US', {
          weekday: 'short',
          month: 'numeric',
          day: 'numeric'
      }).replace(',', '') + '<br>' + new
      Date(x.gameDate).toLocaleTimeString('en-US', {
          hour: 'numeric',
          minute: '2-digit',
          hour12: true,
          timeZone: 'America/New_York'
      })
  - name: Game
    data: games_list
    modify: |-
      `${x.status.statusCode === 'P' || x.status.statusCode === 'S' ||
      x.status.statusCode === 'I' ? 
          `<img src="https://www.mlbstatic.com/team-logos/team-cap-on-dark/${x.teams.away?.team?.id}.svg" 
           style="width: 20px; height: 20px; vertical-align: middle; margin-right: 5px;">
           ${x.teams.away?.team?.abbreviation || 'N/A'}
           <span style="font-size: 12px; color: gray;">
             (${x.teams.away?.leagueRecord?.wins || '0'}-${x.teams.away?.leagueRecord?.losses || '0'})
           </span><br>
           <img src="https://www.mlbstatic.com/team-logos/team-cap-on-dark/${x.teams.home?.team?.id}.svg" 
           style="width: 20px; height: 20px; vertical-align: middle; margin-right: 5px;">
           ${x.teams.home?.team?.abbreviation || 'N/A'}
           <span style="font-size: 12px; color: gray;">
             (${x.teams.home?.leagueRecord?.wins || '0'}-${x.teams.home?.leagueRecord?.losses || '0'})
           </span>`
           : ''}`
  - name: Probable Pitchers
    data: games_list
    modify: |-
      `${x.teams.away.probablePitcher ? 
        `<a href="https://www.mlb.com/player/${x.teams.away.probablePitcher.nameSlug}" target="_blank">
          <img src="https://midfield.mlbstatic.com/v1/people/${x.teams.away.probablePitcher.id}/silo/60?zoom=1.2" 
               style="width:20px; height:20px; border-radius:50%; margin-right:5px;"></a>` 
        : ''} 
        ${x.teams.away.probablePitcher ? x.teams.away.probablePitcher.lastName : 'TBD'}
        ${x.teams.away.probablePitcher && x.teams.away.probablePitcher.stats && x.teams.away.probablePitcher.stats[3] ? 
        '(' + x.teams.away.probablePitcher.stats[3].stats.summary + ')' : ''} <br>
       ${x.teams.home.probablePitcher ? 
        `<a href="https://www.mlb.com/player/${x.teams.home.probablePitcher.nameSlug}" target="_blank">
          <img src="https://midfield.mlbstatic.com/v1/people/${x.teams.home.probablePitcher.id}/silo/60?zoom=1.2" 
               style="width:20px; height:20px; border-radius:50%; margin-right:5px;"></a>` 
        : ''} 
        ${x.teams.home.probablePitcher ? x.teams.home.probablePitcher.lastName : 'TBD'}
        ${x.teams.home.probablePitcher && x.teams.home.probablePitcher.stats && x.teams.home.probablePitcher.stats[3] ? 
        '(' + x.teams.home.probablePitcher.stats[3].stats.summary + ')' : ''}`

Hope this helps! Thank you for your rest sensor details.

1 Like

Stuck and hopefully someone can help.
I have a flex-table and wanted to have row-cells have a column that contains actions.

Read through everything but cannot get it to work (even the simple examples).

This shows the data table is fine:

The actual content for that cell should be passed to some action,
SUPPOSEDLY data-table supports this, allowing for an action.

Tried this and many other attempts, nothing is “clickable” I guess:

                  - name: Track
                    data: song_search
                    modify: x.uri
                    tap_action:
                      action: spotifyplus.add_player_queue_items
                      target:
                        entity_id: media_player.spotifyplus_kevin_brown
                      data:
                        uris: |
                          x.uri

Executing that code does as expected, so it just never runs or click (hold, double-click) or anything

The documentation was ahead of the release. Grab v0.7.9, released this morning.

Also, action must be perform-action, and then perform_action calls your actual action. From the HA docs:

action string REQUIRED

Action to perform (more-info, toggle, perform-action, navigate, url, assist, none)

perform_action string (Optional, default: none)

Action to perform (e.g., media_player.media_play_pause) when the action is defined as perform-action

And, the x syntax only works on the modify option. You’ll need to use a cell[n] reference for uris under data. BTW, have you tried using data: song_search.uri and omitting the modify option?

Finally, some actions will not require (or tolerate) having the target entity passed, so if you see:

Failed to perform the action … extra keys not allowed @ data[‘entity_id’]

add the line:

target: {}

at the same indent level as data.

Thank you. I was able to make it work but see a limitation (or maybe I don’t get it) …

Can you use cell notation to refer to a different cell or?

Given this example:

                  - name: URi
                    hidden: true
                    data: song_search.uri
                  - name: Track
                    data: song_search
                    modify: >-
                      '<div><img src="' + x.image_url + '"
                      style="height:50px;"/>' +'</div>'
                    tap_action:
                      action: perform-action
                      perform_action: spotifyplus.add_player_queue_items
                      target: {}
                      data:
                        entity_id: media_player.spotifyplus_kevin_brown
                        uris: cell[3]

What I want is that the long URi is not shown, but I can use that value. If I just use the URi in the clickable cell (using cell[3]) it executes the action. If use hidden: true for the column, it does not work.

Workaround for now:

                css:
                  table+: 'padding: 0px; width: 100%;'
                  tbody tr td:nth-child(1): 'display: none;'
                  thead tr th:nth-child(1): 'display: none;'
                  tbody tr:hover: 'background-color: lightgreen!important;'

Using CSS to hide the cell and the header works.

Use col[n] to access all columns, including hidden ones. Check the docs under:

Also, since your action needs an entity, you can move it up from data under target and get rid of the braces. Should work either way.

Seems 0.7.9 broke the horizontal scrollbar example. It works after reverting back to 0.7.8

My config looks like this:

type: custom:flex-table-card
entities:
  include: ...
columns: ...
css:
  table+: "padding: 0px"
  tbody tr+: "user-select: text"
card_mod:
  style: |
    ha-card {
      overflow: auto;
      max-height: 1000px;
    }
    tbody tr:hover {
      background-color: coral !important;
    }