Perspective: Display tags value in table format

Hi Forum,

What is the best strategy to display tag values in table format, that is tag's names in first column and tag's values on the second?

Right now, I use one row template with tagName and tagValues and use flex container to stack them up.
It is a bit tricky to align them though.

1 Like

Where's the data coming from and what format is it in? (Is it a dataset, a list, or what? Can you post an example?)


Tip: mind your apostrophes.

  • One tag's name.
  • Multiple tags' names.
    It makes a difference to readability and errors can cause ambiguity in the writing.

Just use a table. The data in the table's two columns would be tag name and tag path. For the latter, configure a column view. The column view would take the tag path and use indirect binding to display the tag value instead.

{No scripting!}

I thought of using a table initially, but cannot imagine passing a dynamic path into manual populated dataset and into the table and table will display the tag's value.

I will explore this.

Thank you

The data sources are random with no relationship.
I would like to display each tagName and tagValues in table format.

With that being said, I need to enter tag's name individually, and enter its path individual.

This is a "get you going" method of exploring Ignition. It's not a great layout for maintainability, etc., but should give you some ideas of how stuff works.

  1. Drop a Table component into the view.
  2. Expand the data and delete any items that are in it. (Use right-click.)
  3. Create array element 0 as an "object".
  4. Add in a value as shown.
  5. Add in a second value as shown.
  6. Click in the gutter to create a binding.
  7. Make it a tag binding.
  8. Use the tag finder to add the path to the tag.
  9. You should get something like this.
    Click OK and repeat for as many tags as you've got.

This makes me think you're trying to use a coordinate container for this which is definitely the wrong container type for a table-like group of components. You should be using a flex container instead.

That said, as others have said, for an actual table, use a table. There are instances though where you might want to use a flex repeater to repeat a row template. However you can also use a Table to repeat row templates too. This is useful if you have a large number of rows as you can use the virtualised mode to only load rows displayed which can significantly help with performance

I just created a bare-bones example.

Sample view with a table. Note, in the table's columns property, how the Value column's render is set to view:

{
  "custom": {},
  "params": {},
  "props": {},
  "root": {
    "children": [
      {
        "children": [
          {
            "meta": {
              "name": "Table1"
            },
            "position": {
              "basis": "400px",
              "grow": 1
            },
            "propConfig": {
              "custom.filtered": {
                "access": "PRIVATE"
              },
              "custom.filteredDS": {
                "access": "PRIVATE"
              },
              "custom.rawData": {
                "access": "PRIVATE"
              }
            },
            "props": {
              "columns": [
                {
                  "align": "center",
                  "boolean": "checkbox",
                  "dateFormat": "MM/DD/YYYY",
                  "editable": false,
                  "field": "Name",
                  "filter": {
                    "boolean": {
                      "condition": ""
                    },
                    "date": {
                      "condition": "",
                      "value": ""
                    },
                    "enabled": false,
                    "number": {
                      "condition": "",
                      "value": ""
                    },
                    "string": {
                      "condition": "",
                      "value": ""
                    },
                    "visible": "on-hover"
                  },
                  "footer": {
                    "align": "center",
                    "justify": "left",
                    "style": {
                      "classes": ""
                    },
                    "title": ""
                  },
                  "header": {
                    "align": "center",
                    "justify": "left",
                    "style": {
                      "classes": ""
                    },
                    "title": ""
                  },
                  "justify": "auto",
                  "nullFormat": {
                    "includeNullStrings": false,
                    "nullFormatValue": "",
                    "strict": false
                  },
                  "number": "value",
                  "numberFormat": "0,0.##",
                  "progressBar": {
                    "bar": {
                      "color": "",
                      "style": {
                        "classes": ""
                      }
                    },
                    "max": 100,
                    "min": 0,
                    "track": {
                      "color": "",
                      "style": {
                        "classes": ""
                      }
                    },
                    "value": {
                      "enabled": true,
                      "format": "0,0.##",
                      "justify": "center",
                      "style": {
                        "classes": ""
                      }
                    }
                  },
                  "render": "auto",
                  "resizable": true,
                  "sort": "none",
                  "sortable": true,
                  "strictWidth": false,
                  "style": {
                    "classes": ""
                  },
                  "toggleSwitch": {
                    "color": {
                      "selected": "",
                      "unselected": ""
                    }
                  },
                  "viewParams": {},
                  "viewPath": "",
                  "visible": true,
                  "width": ""
                },
                {
                  "align": "center",
                  "boolean": "checkbox",
                  "dateFormat": "MM/DD/YYYY",
                  "editable": false,
                  "field": "Value",
                  "filter": {
                    "boolean": {
                      "condition": ""
                    },
                    "date": {
                      "condition": "",
                      "value": ""
                    },
                    "enabled": false,
                    "number": {
                      "condition": "",
                      "value": ""
                    },
                    "string": {
                      "condition": "",
                      "value": ""
                    },
                    "visible": "on-hover"
                  },
                  "footer": {
                    "align": "center",
                    "justify": "left",
                    "style": {
                      "classes": ""
                    },
                    "title": ""
                  },
                  "header": {
                    "align": "center",
                    "justify": "left",
                    "style": {
                      "classes": ""
                    },
                    "title": ""
                  },
                  "justify": "auto",
                  "nullFormat": {
                    "includeNullStrings": false,
                    "nullFormatValue": "",
                    "strict": false
                  },
                  "number": "value",
                  "numberFormat": "0,0.##",
                  "progressBar": {
                    "bar": {
                      "color": "",
                      "style": {
                        "classes": ""
                      }
                    },
                    "max": 100,
                    "min": 0,
                    "track": {
                      "color": "",
                      "style": {
                        "classes": ""
                      }
                    },
                    "value": {
                      "enabled": true,
                      "format": "0,0.##",
                      "justify": "center",
                      "style": {
                        "classes": ""
                      }
                    }
                  },
                  "render": "view",
                  "resizable": true,
                  "sort": "none",
                  "sortable": true,
                  "strictWidth": false,
                  "style": {
                    "classes": ""
                  },
                  "toggleSwitch": {
                    "color": {
                      "selected": "",
                      "unselected": ""
                    }
                  },
                  "viewParams": {},
                  "viewPath": "TagColumn",
                  "visible": true,
                  "width": ""
                }
              ],
              "data": {
                "$": [
                  "ds",
                  192,
                  1690756907117
                ],
                "$columns": [
                  {
                    "data": [
                      "Gateway CPU",
                      "Gateway RAM"
                    ],
                    "name": "Name",
                    "type": "String"
                  },
                  {
                    "data": [
                      "[default]Forum/GatewayCPU",
                      "[default]Forum/GatewayMemory"
                    ],
                    "name": "Value",
                    "type": "String"
                  }
                ]
              },
              "pager": {
                "bottom": false
              }
            },
            "type": "ia.display.table"
          }
        ],
        "meta": {
          "name": "FlexContainer"
        },
        "position": {
          "basis": "34px",
          "grow": 1
        },
        "props": {
          "direction": "column"
        },
        "type": "ia.container.flex"
      }
    ],
    "meta": {
      "name": "root"
    },
    "props": {
      "direction": "column"
    },
    "type": "ia.container.flex"
  }
}

The above table uses this as the rendering view for the column. Note that the value passed into this view is the tagpath from the Value column:

{
  "custom": {
    "fmt": "#,##0.000",
    "tag": 0.01669449081803005
  },
  "params": {
    "row": "value",
    "rowIndex": "value",
    "value": "[default]Forum/GatewayCPU"
  },
  "propConfig": {
    "custom.fmt": {
      "binding": {
        "config": {
          "fallbackDelay": 2.5,
          "mode": "indirect",
          "references": {
            "1": "{view.params.value}"
          },
          "tagPath": "{1}.FormatString"
        },
        "type": "tag"
      },
      "persistent": true
    },
    "custom.tag": {
      "binding": {
        "config": {
          "fallbackDelay": 2.5,
          "mode": "indirect",
          "references": {
            "1": "{view.params.value}"
          },
          "tagPath": "{1}"
        },
        "type": "tag"
      },
      "persistent": true
    },
    "params.row": {
      "paramDirection": "input",
      "persistent": true
    },
    "params.rowIndex": {
      "paramDirection": "input",
      "persistent": true
    },
    "params.value": {
      "paramDirection": "input",
      "persistent": true
    }
  },
  "props": {
    "defaultSize": {
      "height": 42,
      "width": 233
    }
  },
  "root": {
    "children": [
      {
        "meta": {
          "name": "Label"
        },
        "position": {
          "basis": "32px",
          "grow": 1
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "config": {
                "expression": "numberFormat({view.custom.tag}, {view.custom.fmt})"
              },
              "type": "expr"
            }
          }
        },
        "props": {
          "style": {
            "textAlign": "right"
          }
        },
        "type": "ia.display.label"
      }
    ],
    "meta": {
      "name": "root"
    },
    "props": {
      "direction": "column",
      "style": {
        "paddingLeft": "0.5em",
        "paddingRight": "1em"
      }
    },
    "type": "ia.container.flex"
  }
}

Adjust your source dataset for the table as desired.

Note that the rendering view only handles numbers, and expects the tag to have a valid .FormatString. Fortunately, numeric tags have valid default format strings.

1 Like

So I have 6 columns, that are, tagName, value, tagName, value, tagName, value, Respectively.

Say in this table I have 3 rows.

So I use Flex Container and set to Direction to Column.
Within this flex, I use another flex and set Direction to Row.
In this row Container I have 3 items (tagName - value pair - a flex view), I also use coordinate containers in between to act as fillers.

These tagNames have different text length, different basis px.
As a result, when I increase the layout size of the parent flex container, they won't be aligned.

I should be able to make mockup data and take a screenshot.
But hope you get what I mean, if there is easy way to align these, I am all ears.
As the table option might not be a solution for this scenario because some data I want to display and input field and status indicator box.

below is the screenshot:

Also attach, is the below export:
image
WorkArea_v005_2023-07-31_2103.zip (16.2 KB)

First we need to make 3 lines span into single:
this
tag
value
into "this tag value" (single line)

What is the trick here to get them aligned?

Edit:
I finally manage to align the items, in a form like a table.

Thanks I will play with this.

This is very straight forward and very helpful visual tool.
This definitely should work.
I will also try this.

I am sorry. I do not follow. How do I use the code you posted? I see that its an object..
Do I import this code or paste it somewhere?

Create two views, doesn't matter what container type. Copy Phil's first json code, shift+right click on the first new View and click "Paste JSON" (down the bottom). Do the same for the other JSON into the 2nd new view.

3 Likes

And then fix up the table's source data (constant) to have tag paths from your environment.

Sounds good. I will try this.

Quick Question, how do you clear all data from the newly dragged table?

I usually set the data to a value type and then back to an array. Otherwise deleting all of the items is slow and painful

Got it. I was binding it to null then remove the binding.

Another problem I encountered, with using Column Property.

I understand that, this is use to format the given column.
I only have one column "timestamp" that I need to format.

But when I add this format to one column, other columns will not show..
Is this really the case?
My problem is, I have greater than 10 columns.
I have to add columns on this property for them to show up?
What if my datasets has dynamic number of columns?

Yes.

Yes. If you define any columns, then only those defined will show in the Table

Bind your props.columns to a script transform to dynamically create the columns.