Real-Time Sports Scores w/ TeamTracker and TeamTracker-Card (Beta)

Here is the full YAML for the Dashboard:

views:
  - theme: Backend-selected
    title: Sports
    type: panel
    icon: mdi:strategy
    badges: []
    cards:
      - type: custom:tabbed-card
        styles:
          '--mdc-theme-primary': green
          '--mdc-tab-text-label-color-default': gray
          '--mdc-typography-button-font-size': 12px
        tabs:
          - attributes:
              label: NHL Standings
            card:
              type: markdown
              content: '**Coming Soon!**'
          - attributes:
              label: NHL Postgame
              icon: mdi:hockey-sticks
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NHL" -%}
                    {%- if states(team) == "POST" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: NHL Live
              icon: mdi:hockey-puck
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NHL" -%}
                    {%- if states(team) == "IN" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: NHL Pregame
              icon: mdi:blood-bag
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NHL" -%}
                    {%- if states(team) == "PRE" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: MLB Standings
            card:
              type: markdown
              content: '**Coming Soon!**'
          - attributes:
              label: MLB Postgame
              icon: mdi:baseball
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "MLB" -%}
                    {%- if states(team) == "POST" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: MLB Live
              icon: mdi:baseball-bat
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "MLB" -%}
                    {%- if states(team) == "IN" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: MLB Pregame
              icon: mdi:baseball-diamond
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "MLB" -%}
                    {%- if states(team) == "PRE" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: NFL Standings
            card:
              type: markdown
              content: '**Coming Soon!**'
          - attributes:
              label: NFL Postgame
              icon: mdi:football-helmet
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NFL" -%}
                    {%- if states(team) == "POST" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: NFL Live
              icon: mdi:football
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NFL" -%}
                    {%- if states(team) == "IN" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
          - attributes:
              label: NFL Pregame
              icon: mdi:strategy
            card:
              type: custom:auto-entities
              unique: true
              show_empty: false
              card:
                type: custom:layout-card
                layout_type: masonry
              card_param: cards
              filter:
                template: |
                  {%- for team in integration_entities("teamtracker") -%}
                    {%- if state_attr(team, "league") == "NFL" -%}
                    {%- if states(team) == "PRE" -%}
                    {%- if state_attr(team, "team_homeaway") == "home" -%}
                      {{{"type": "custom:teamtracker-card",
                        "entity": team }}},
                    {%- endif -%}
                    {%- endif -%}
                    {%- endif -%}
                  {%- endfor -%}
                exclude:
                  - entity_id: '*team_tracker*'
              sort:
                method: attribute
                attribute: date
title: Sports Scores
1 Like

Yeah I figured it out. Had to change my View setting to “Panel”

Now to figure out how to get the right settings for standings in the cutom:tabbed-card.

@vasqued2 … Good start. I use this for NHL and I can see the light.

- platform: rest
  scan_interval: 36000
  name: NHL Standings
  unique_id: sensor.nhl_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/hockey/nhl/standings?type=2&level=2
  value_template: "{{ now() }}"
  json_attributes:
      - children

I may need one level more, I will need to check the actual result as that is Divisional. I am understanding this now.

Yes use 3 and 3 and you get by Conference and Division in the Conference.
Then this should be in four flex-tables not one. IN pseudo codehere …

East-ATL … children[0].children[0].standings.entries.team
East-MET… children[0].children[1].standings.entries.team
West-CEN … children[1].children[0].standings.entries.team
West-PAC … children[1].children[1].standings.entries.team

Ok so if I do this…

- platform: rest
    name: MLS_Standings_test
    scan_interval: 7200
    resource: https://site.web.api.espn.com/apis/v2/sports/soccer/usa.1/standings?type=0&level=0
    value_template: "{{ now() }}"
    json_attributes:
      - children   

Looks like this pulls all MLS teams broken up by conferences…but now how do I pull the data into the flex-table?

children:
  - uid: s:600~l:770~g:1
    id: '1'
    name: Eastern Conference
    abbreviation: East
    standings:
      id: '0'
      name: overall
      displayName: Overall Standings
      links:
        - language: en-US
          rel:
            - standings
            - desktop
          href: https://www.espn.com/soccer/table/_/league/usa.1
          text: Table
          shortText: Standings
          isExternal: false
          isPremium: false
      season: 2023
      seasonType: 1
      entries:
        - team:
            id: '182'
            uid: s:600~t:182
            location: Chicago Fire FC
            name: Chicago Fire FC
            abbreviation: CHI
            displayName: Chicago Fire FC
            shortDisplayName: Chicago
            isActive: true
            logos:
              - href: https://a.espncdn.com/i/teamlogos/soccer/500/182.png
     

No idea. I have tried dozens of combinations to flex-table and none work as they should. I am likely going to abandon it as it is lame and really can only handle data one level deep. If anyone has an example otherwise, I would love to see it but I can write jinja all dat long to get at everything, but the data selector just cannot more than one level.

Take the simplest of all examples as I see it:

type: custom:flex-table-card
title: Standings
sort_by: place
entities:
  include: sensor.nhl_standings
columns:
  - name: Name
    data: children
    modify: |
      '<div>' + x.name + '</div>'
    align: left

This works and gives you this:

image

So lets try to go one level deeper.

type: custom:flex-table-card
title: Standings
sort_by: place
entities:
  include: sensor.nhl_standings
columns:
  - name: Name
    data: children.children[0]
    modify: |
      '<div>' + x.name + '</div>'
    align: left

image

Yet it should work. Let’s prove it … let’s change the it just a bit

type: custom:flex-table-card
title: Standings
sort_by: place
entities:
  include: sensor.nhl_standings
columns:
  - name: Name
    data: children
    modify: |
      '<div>' + x.children[0].name + '</div>'
    align: left

image

And this shows two things.

(1) The data selector cannot be more than one level deep. If someone can prove it can, show me I would love to see it.
(2) This makes it totally unusable for this application because it will only iterate over the “data” which is children which will always be two in this case (one for each conference). And here is the proof for that:

type: custom:flex-table-card
title: Standings
sort_by: place
entities:
  include: sensor.nhl_standings
columns:
  - name: Name
    data: children
    modify: |
      '<div>' + x.children[0].standings.entries[0].team.name + '</div>'
    align: left

image

Two teams. Not every team because it iterates over the data: which has two conferences so you only get two teams. And because it appears (not as their documentation states) that you can put paths into the data: YAML, it does not work for anything more than one level.

In other words, someone show an example like this which I cannot find anywhere:

data: level1.level2.level3

While their documentation states you can, I am sorry … it does not work.

Now, I can easily do this in templates:

{% for entry in state_attr('sensor.nhl_standings','children')[0].children[0].standings.entries | list %}
{{ entry.team.name }}
{% endfor %}

So in templates one could easily build out what is needed. Problem is throwing that into Markdown a’int the prettiest things but I guess if one one has a solution then that is the way to go. In fact, the more I thin about it I think injecting a table in markdown is the way because one markdown card can have all the stats.

On to writing it

Here.

I suspected that was what would be needed. I would have preferred one sensor with the data and not four for the NHL. One sensor four flex tables each with different data:

The documentation alludes to this as possible by stating you can have paths in the data:

Is it not possible?

Specifically, I have this (abbreviated but enough to understand):

children:
  - uid: s:70~l:90~g:7
    id: '7'
    name: Eastern Conference
    abbreviation: East
    children:
      - uid: s:70~l:90~g:32
        id: '32'
        name: Atlantic Division
        abbreviation: ATL
        standings:
          id: '3'
          name: wildcard
          displayName: Wild Card Standings
          links:
            - language: en-US
              rel:
                - standings
                - desktop
              href: https://www.espn.com/nhl/standings/_/group/32
              text: Table
              shortText: Standings
              isExternal: false
              isPremium: false
          season: 2023
          seasonType: 2
          entries:
            - team:
                id: '2'
                uid: s:70~l:90~t:2
                location: Buffalo
                name: Sabres
                abbreviation: BUF
                displayName: Buffalo Sabres
                shortDisplayName: Sabres
                isActive: true

data: childern and x.name is correct and yields “Eastern Conference”, “Western Conference”)

Based on this from the documentation – “When accessing attributes, sometimes an attribute object will itself contain objects. In that case, you can access the lower object using dotted notation. eg: object1.object2.field1”

I would have exepected data:children.children to give me the four named divisions, or childern.children[0] give me the first. But alas it does not. It is just an error.

I assume this means that your sensor attributes are at the grouping level and the data: attribute is the row repeater and can only be one level under the sensor main attribute?

Can the flex-table-card do a sortby?

This could be a left field solution - but what about using Markdown?

resource: https://site.web.api.espn.com/apis/v2/sports/hockey/nhl/standings?type=0&level=4
sensor:
  name: scoreboard_nhl
  value_template: "{{ now() }}"
  json_attributes:
    - children
scan_interval: 3600
type: custom:vertical-stack-in-card
cards:
  - type: grid
    square: false
    columns: 1
    cards:
      - type: custom:mushroom-template-card
        primary: NHL (All Teams)
        icon: mdi:hockey-puck
        icon_color: green
  - type: markdown
    content: >-
      {% for conf in state_attr('sensor.scoreboard_nhl', 'children') %} {% for
      division in conf.children %}

      ### {{conf.name}}, {{division.name }}

      |Team|Logo|GP|W|L|PD|Pts|

      |:--|:--:|:--:|:--:|:--:|:--:|:--:|

      {%- for team in division.standings.entries %}

      |{{team.team.displayName}}|<img
      src="{{team.team.logos[1].href}}">|{{team.stats[3].value|int}}|{{team.stats[10].value|int}}|{{team.stats[4].value|int}}|{{team.stats[8].value|int}}:{{team.stats[7].value|int}}|{{team.stats[6].value|int}}|

      {%- endfor %}

      {% endfor %}

      {% endfor %}
    card_mod:
      style:
        ha-markdown: |
          ha-card.type-markdown { box-shadow: none; }
          .no-header {padding-top: 0px !important; }
        ha-markdown$: >
          table { width: 100%; padding: 16px; border-collapse: collapse;
          padding: 0px; }

          thead th { height: 1em; }

          tr td { padding-left: 0.5em; padding-right: 0.5em;  }

          th { padding-left: 0.5em; padding-right: 0.5em;  }

          tbody tr:nth-child(odd) { background-color:
          var(--table-row-background-color);  }

          tbody tr:nth-child(even) { background-color:
          var(--table-row-alternative-background-color);  }

          tbody tr td:nth-child(2) { width: 10%; }

          th ha-icon { height: 1em; vertical-align: top;  } 

EDIT - this code can help you find the right column number

{% set ns = namespace(count = 0) %}
{% for x in states.sensor.scoreboard_nhl.attributes.children[0].children[0].standings.entries[0].stats %}
{{ ns.count }} {{x.name}} {{x.displayValue}}
{%- set ns.count = ns.count+1 %}
{%- endfor %}

I already did the multiple sensor solution. Flex-table-card - #58 by kbrown01

No problem - perhaps someone else may benefit from the alternate approach

But of course! In fact if you look at the above I did say that Markdown can do it.
The issue though is that markdown was complex at best and would require a lot of card-mod/css styling to make it look decent, you have done a great job above for sure.

You approach could have another significant benefit that should be pointed out. Having all the data in one sensor by conference and division would allow you to have three markdown cards. One as you have done by division, one by conference and one overall with every team … all sorted by points and even a wild-card one by conference plus divisional leaders.

I was only hoping that all of that could be done with flex-table but alas, it does not seem that “flexy”.

As a side note I have that almost exact same “stat name finder” in my Developer tools. I did exactly that to figure out what all the stat names were and their index to plug in.

I thought I would post this here for everyone to use/comment/change as you please.
I created a Dashboard Side Panel that uses decluttering and tabbed cards for all NHL, MLB, NFL standings and PRE, IN and POST stat views (sorry NBA fans!)

It uses three main REST sensors to get the overall stats and then template sensors for each conference. Of course it uses teamtracker for individual teams for each of the sports, not posted here.

Some examples:

NHL Standings by Division:

NHL Standings Overall:

NHL Pregame:

The sensors are defines in my included sensor.yaml as follows. Note that I also set seasontype in the query to “2” to get the regular season. This is not built for pre-season although it could be easily done if you wanted pre-season stats.

###
### Divisional Stats
###
- platform: rest
  scan_interval: 36000
  name: NHL Standings
  unique_id: sensor.nhl_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/hockey/nhl/standings?seasontype=2&type=0&level=3
  value_template: "{{ now() }}"
  json_attributes:
      - children

- platform: rest
  scan_interval: 36000
  name: MLB Standings
  unique_id: sensor.mlb_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/baseball/mlb/standings?seasontype=2&type=0&level=3
  value_template: "{{ now() }}"
  json_attributes:
      - children

- platform: rest
  scan_interval: 36000
  name: NFL Standings
  unique_id: sensor.nfl_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/football/nfl/standings?seasontype=2&type=0&level=3
  value_template: "{{ now() }}"
  json_attributes:
      - children

The template sensors are defined in my included template.yaml as:

###
### MLB Divisions
###
  - name: MLB American East
    unique_id: sensor.mlb_american_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: MLB American Central
    unique_id: sensor.mlb_american_central
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: MLB American West
    unique_id: sensor.mlb_american_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[0]['children'][2]['standings']['entries'] }}"
  - name: MLB National East
    unique_id: sensor.mlb_national_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: MLB National Central
    unique_id: sensor.mlb_national_central
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[1]['children'][1]['standings']['entries'] }}"
  - name: MLB National West
    unique_id: sensor.mlb_national_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.mlb_standings','children')[1]['children'][2]['standings']['entries'] }}"
###
### NHL Divisions
###
  - name: NHL East Atlantic
    unique_id: sensor.nhl_east_atlantic
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: NHL East Metropolitan
    unique_id: sensor.nhl_east_metropolitan
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: NHL West Central
    unique_id: sensor.nhl_west_central
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: NHL West Pacific
    unique_id: sensor.nhl_west_pacific
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][1]['standings']['entries'] }}"
###
### NFL Divisions
###
  - name: NFL AFC East
    unique_id: sensor.nfl_afc_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: NFL AFC North
    unique_id: sensor.nfl_afc_north
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: NFL AFC South
    unique_id: sensor.nfl_afc_south
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][2]['standings']['entries'] }}"
  - name: NFL AFC West
    unique_id: sensor.nfl_afc_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][3]['standings']['entries'] }}"
  - name: NFL NFC East
    unique_id: sensor.nfl_nfc_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: NFL NFC North
    unique_id: sensor.nfl_nfc_north
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][1]['standings']['entries'] }}"
  - name: NFL NFC South
    unique_id: sensor.nfl_nfc_south
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][2]['standings']['entries'] }}"
  - name: NFL NFC West
    unique_id: sensor.nfl_nfc_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][3]['standings']['entries'] }}"

And the whole dashboard is like this:

decluttering_templates:
  nhl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px'
        tbody tr td:first-child: 'width: 20%;'
        tbody tr td:nth-child(n+2): 'width: 5%;'
        tbody tr:hover: 'background-color: lightgreen!important;'
        tbody tr td:nth-child(6): 'background-color: #E3F5D4;'
      card_mod:
        style:
          $: |
            .card-header {
               padding: 12px 0px 8px 4px!important;
               font-size: 16px!important;
               line-height: 18px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
      sort_by: entries-
      columns:
        - hidden: true
          data: entries
          modify: x.stats[6].value
        - name: Team
          data: entries
          modify: x.team.displayName
        - name: GP
          data: entries
          modify: x.stats[3].displayValue
        - name: W
          data: entries
          modify: x.stats[10].displayValue
        - name: L
          data: entries
          modify: x.stats[4].displayValue
        - name: OTL
          data: entries
          modify: x.stats[11].displayValue
        - name: PTS
          data: entries
          modify: x.stats[6].displayValue
        - name: RW
          data: entries
          modify: x.stats[14].displayValue
        - name: ROW
          data: entries
          modify: x.stats[15].displayValue
        - name: SOW
          data: entries
          modify: x.stats[17].displayValue
        - name: SOL
          data: entries
          modify: x.stats[16].displayValue
        - name: HOME
          data: entries
          modify: x.stats[19].displayValue
        - name: AWAY
          data: entries
          modify: x.stats[20].displayValue
        - name: GF
          data: entries
          modify: x.stats[8].displayValue
        - name: GA
          data: entries
          modify: x.stats[7].displayValue
        - name: DIFF
          data: entries
          modify: x.stats[13].displayValue
        - name: L10
          data: entries
          modify: x.stats[21].summary
        - name: STRK
          data: entries
          modify: x.stats[9].displayValue
  mlb_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px'
        tbody tr td:first-child: 'width: 20%;'
        tbody tr td:nth-child(n+2): 'width: 5%;'
        tbody tr:hover: 'background-color: lightgreen!important;'
        tbody tr td:nth-child(6): 'background-color: #E3F5D4;'
      card_mod:
        style:
          $: |
            .card-header {
               padding: 12px 0px 8px 4px!important;
               font-size: 16px!important;
               line-height: 18px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
      sort_by: entries-
      columns:
        - hidden: true
          data: entries
          modify: x.stats[16].value
        - name: Team
          data: entries
          modify: x.team.displayName
        - name: GP
          data: entries
          modify: x.stats[7].displayValue
        - name: W
          data: entries
          modify: x.stats[17].displayValue
        - name: L
          data: entries
          modify: x.stats[9].displayValue
        - name: T
          data: entries
          modify: x.stats[15].displayValue
        - name: PCT
          data: entries
          modify: x.stats[16].displayValue
        - name: GB
          data: entries
          modify: x.stats[6].displayValue
        - name: PS
          data: entries
          modify: x.stats[10].displayValue
        - name: HOME
          data: entries
          modify: x.stats[33].displayValue
        - name: AWAY
          data: entries
          modify: x.stats[34].displayValue
        - name: RS
          data: entries
          modify: x.stats[13].displayValue
        - name: RA
          data: entries
          modify: x.stats[12].displayValue
        - name: DIFF
          data: entries
          modify: x.stats[27].displayValue
        - name: L10
          data: entries
          modify: x.stats[37].summary
        - name: STRK
          data: entries
          modify: x.stats[14].displayValue
  nfl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px'
        tbody tr td:first-child: 'width: 2%;'
        tbody tr td:nth-child(2): 'width: 20%;'
        tbody tr td:nth-child(n+3): 'width: 6%;'
        tbody tr:hover: 'background-color: lightgreen!important;'
        tbody tr td:nth-child(7): 'background-color: #E3F5D4;'
      card_mod:
        style:
          $: |
            .card-header {
               padding: 12px 0px 8px 4px!important;
               font-size: 16px!important;
               line-height: 18px!important;
               font-weight: bold!important;
             }
      sort_by: entries-
      entities:
        include: '[[entity]]'
      columns:
        - hidden: true
          data: entries
          modify: x.stats[9].displayValue
        - name: C
          data: entries
          modify: x.stats[0].displayValue
        - name: Team
          data: entries
          modify: x.team.displayName
        - name: GP
          data: entries
          modify: x.stats[10].value + x.stats[3].value + x.stats[8].value
        - name: W
          data: entries
          modify: x.stats[10].displayValue
        - name: L
          data: entries
          modify: x.stats[3].displayValue
        - name: T
          data: entries
          modify: x.stats[8].displayValue
        - name: PCT
          data: entries
          modify: x.stats[9].displayValue
        - name: HOME
          data: entries
          modify: x.stats[16].displayValue
        - name: AWAY
          data: entries
          modify: x.stats[17].displayValue
        - name: DIV
          data: entries
          modify: x.stats[18].displayValue
        - name: CONF
          data: entries
          modify: x.stats[19].displayValue
        - name: PF
          data: entries
          modify: x.stats[6].displayValue
        - name: PA
          data: entries
          modify: x.stats[5].displayValue
        - name: DIFF
          data: entries
          modify: x.stats[1].displayValue
        - name: STRK
          data: entries
          modify: x.stats[7].displayValue
  game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
      card_param: cards
      filter:
        template: |
          {%- for team in integration_entities("teamtracker") -%}
            {%- if state_attr(team, "league") == "[[sport]]" -%}
            {%- if states(team) == "[[status]]" -%}
            {%- if state_attr(team, "team_homeaway") == "home" -%}
              {{{"type": "custom:teamtracker-card",
                "entity": team }}},
            {%- endif -%}
            {%- endif -%}
            {%- endif -%}
          {%- endfor -%}
        exclude:
          - entity_id: '*team_tracker*'
      sort:
        method: attribute
        attribute: date
views:
  - theme: Backend-selected
    title: Sports
    type: panel
    icon: mdi:strategy
    badges: []
    cards:
      - type: custom:tabbed-card
        styles:
          '--mdc-theme-primary': green
          '--mdc-tab-text-label-color-default': gray
          '--mdc-typography-button-font-size': 12px
        tabs:
          - attributes:
              label: NHL Standings
              icon: mdi:ballot
            card:
              type: custom:tabbed-card
              styles:
                '--mdc-theme-primary': green
                '--mdc-tab-text-label-color-default': gray
                '--mdc-typography-button-font-size': 12px
              tabs:
                - attributes:
                    label: Divisional
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: Eastern Atlantic
                          - entity: sensor.nhl_east_atlantic
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: Eastern Metropolitan
                          - entity: sensor.nhl_east_metropolitan
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: West Central
                          - entity: sensor.nhl_west_central
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: West Pacific
                          - entity: sensor.nhl_west_pacific
                - attributes:
                    label: Conference
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: Eastern
                          - entity: sensor.nhl_east_*
                      - type: custom:decluttering-card
                        template: nhl_settings
                        variables:
                          - title: Western
                          - entity: sensor.nhl_west_*
                - attributes:
                    label: Overall
                  card:
                    type: custom:decluttering-card
                    template: nhl_settings
                    variables:
                      - title: Overall
                      - entity: sensor.nhl_*_*
          - attributes:
              label: NHL Postgame
              icon: mdi:hockey-sticks
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: NHL
                - status: POST
          - attributes:
              label: NHL Live
              icon: mdi:hockey-puck
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: NHL
                - status: IN
          - attributes:
              label: NHL Pregame
              icon: mdi:blood-bag
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: NHL
                - status: PRE
          - attributes:
              label: MLB Standings
              icon: mdi:ballot
            card:
              type: custom:tabbed-card
              styles:
                '--mdc-theme-primary': green
                '--mdc-tab-text-label-color-default': gray
                '--mdc-typography-button-font-size': 12px
              tabs:
                - attributes:
                    label: Divisional
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: American League East
                          - entity: sensor.mlb_american_east
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: American League Central
                          - entity: sensor.mlb_american_central
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: American League West
                          - entity: sensor.mlb_american_west
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: National League East
                          - entity: sensor.mlb_national_east
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: National League Central
                          - entity: sensor.mlb_national_central
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: National League West
                          - entity: sensor.mlb_national_west
                - attributes:
                    label: Conference
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: Americal League
                          - entity: sensor.mlb_american_*
                      - type: custom:decluttering-card
                        template: mlb_settings
                        variables:
                          - title: National League
                          - entity: sensor.mlb_national_*
                - attributes:
                    label: Overall
                  card:
                    type: custom:decluttering-card
                    template: mlb_settings
                    variables:
                      - title: Overall
                      - entity: sensor.mlb_*_*
          - attributes:
              label: MLB Postgame
              icon: mdi:baseball
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: MLB
                - status: POST
          - attributes:
              label: MLB Live
              icon: mdi:baseball-bat
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: MLB
                - status: IN
          - attributes:
              label: MLB Pregame
              icon: mdi:baseball-diamond
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: MLB
                - status: PRE
          - attributes:
              label: NFL Standings
              icon: mdi:ballot
            card:
              type: custom:tabbed-card
              styles:
                '--mdc-theme-primary': green
                '--mdc-tab-text-label-color-default': gray
                '--mdc-typography-button-font-size': 12px
              tabs:
                - attributes:
                    label: Divisional
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: American Football Conference East
                          - entity: sensor.nfl_afc_east
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: American Football Conference North
                          - entity: sensor.nfl_afc_north
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: American Football Conference South
                          - entity: sensor.nfl_afc_south
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: American Football Conference West
                          - entity: sensor.nfl_afc_west
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: National Football Conference East
                          - entity: sensor.nfl_nfc_east
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: National Football Conference North
                          - entity: sensor.nfl_nfc_north
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: National Football Conference South
                          - entity: sensor.nfl_nfc_south
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: National Football Conference West
                          - entity: sensor.nfl_nfc_west
                - attributes:
                    label: Conference
                  card:
                    type: custom:stack-in-card
                    mode: vertical
                    cards:
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: American Football Conference
                          - entity: sensor.nfl_afc_*
                      - type: custom:decluttering-card
                        template: nfl_settings
                        variables:
                          - title: National Football Conference
                          - entity: sensor.nfl_nfc_*
                - attributes:
                    label: Overall
                  card:
                    type: custom:decluttering-card
                    template: nfl_settings
                    variables:
                      - title: Overall
                      - entity: sensor.nfl_*_*
          - attributes:
              label: NFL Postgame
              icon: mdi:football-helmet
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: NFL
                - status: POST
          - attributes:
              label: NFL Live
              icon: mdi:football
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: NFL
                - status: IN
          - attributes:
              label: NFL Pregame
              icon: mdi:strategy
            card:
              type: custom:decluttering-card
              template: game_stats
              variables:
                - sport: MLB
                - status: PRE
title: Sports Scores

Big thanks to @Ildar_Gabdullin for assistance in this, sorry for pestering until I understod how things work in flex-table. And I have to say I am now in process of moving many things to use decluttering. That dashboard would have 20 times the lines of code without it.

2 Likes

I got the standings and stats working, however I can’t get the PRE, IN, and POST to show anything. Where did you define these sensors? I found the post here: Real-Time Sports Scores w/ TeamTracker and TeamTracker-Card (Beta) - #230 by kbrown01 but it’s still not showing me anything in the games tabs and I have a red circle exclamation mark with no text (sort of indicating an error in the dashboard code)
I fixed this. Not only was I missing the custom card layout-card, there was also an incorrect double quote character around the custom:teamtracker-card on line 237. Also the NFL Pregame tab was showing MLB Pregame because the decluttering card had MLB for the sport.

Also, is there a way to make the table dynamic in size or allow horizontal scrolling? on the HA Mobile App the right columns (example: on NHL anything after ‘SOL’) get cut off and there’s no way to view anything after that.

Something like this for scrolling (partial snip from top of decluttering_templates for one of the flex tables):

decluttering_templates:
  nhl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 1600px;'
        tbody tr td:first-child: 'width: 20%;'
        tbody tr td:nth-child(n+2): 'width: 5%;'
        tbody tr:hover: 'background-color: lightgreen!important;'
        tbody tr td:nth-child(6): 'background-color: #E3F5D4;'
      card_mod:
        style: |
          ha-card {
              overflow: auto;
            }
          $: |
            .card-header {
               padding: 12px 0px 8px 4px!important;
               font-size: 16px!important;
               line-height: 18px!important;
               font-weight: bold!important;
             }

So adding a fixed table width (you pick what you like for PC dashboard) and then adding overflow:auto on the ha-card itself. This will allow you to scroll the table left/right.

As for the other issues, I will take a look and be sure all is good. I was creating a Git with all the sensors and dashboard view over the next day (while I added NBA too).

Hmmm, that didn’t work. The fixed width worked, but the overflow: auto did not, I still can’t scroll horizontally. I’ll mess around with the code a bit and see if I can get it to scroll.

What platform? Works on my Windows PC in Chrome and Edge and my Android using Chrome.

Windows 10, chrome. Also tried on the HA mobile app for iOS. I did clear cache and refresh the page.

Not sure, works for me. Here is PC Window shrank which pops the scroll bar:

Here is view scrolled on my Android phone (only top table in multiple stats):

I have put everything I have out on GITHUB. You will find all the rest, template and teamtracker sensors for NFL, NHL, MLB and NBA along with the PRE, IN, POST views in a tabbed Dashboard.

Looking for someone that wants to help do the last missing piece! a PLAYOFF/WILDCARD type view under standings. I have yet to implement that yet.

Leave comments on GITHUB or here.