Use of tag() binding in expressions is bad?

hi,

I wanted to get a little clarification on the use of the Tag() binding. I understand it’s bad for performance. What is the appropriate way to structure expressions? For example, say I have:

Analog Indicator view
- Vertical indicator
- Label

The “Analog Indicator” has a Param, DataTag for the root tag.

The Vertical Indicator has an indirect binding to the “DataTag/Value”. it also has an expression checking for limits that uses something like “Tag(DataTag +”/HiLimit”), Tag(DataTag +”/LoLimit”) for several tags., sometimes an extensive list if somebody weas trying to get fancy.

What would be the proper way to accomplish this? Do I create Custom Properties in the “Analog Indicator” view? Can I use the tag() bindings in the custom property? Then reference the result in the Vertical Indicator? Use a reference to the custom property, “view.custom.value” for example.

Most of our template make extensive use of the tag() binding. all of them have at least a couple and some have a dozen or more. This is due to inexperience in house and by an inexperienced integrator.

Now I get to fix it….

Add a custom property for each value you are looking at. Populate those properties with tag or indirect tag bindings (fast). Reference those properties in your expression.

If you’re looking at the same values on multiple expressions across your screen you can benefit from having the properties live at the form or view level so they only get looked up once and propagate changes down through the screen.

5 Likes

Also, the tag() expression is acceptable to use in a tag (e.g an expression tag).

Whenever you want to use the tag() expression function you're probably trying to do (at least) 2 things at once. Just break it into multiple simple, faster steps. The first of which is typically building a string path to the UDT instance where the tag(s) is located so that it can be used in (multiple) indirect bindings.

3 Likes

Thanks. Here is a nice example of an expression binding we have. Should I change this up? There are a lot of tag() expressions. It’s to get the background status color for some equipment…

if(tag({view.params.Tag}+"/Mtr/Sts_Available") = false || tag({view.params.Tag}+"/Mtr/Sts_Oper") && tag({view.params.Tag}+"/Mtr/Sts_Running"), "#000000",
if(tag({view.params.Tag}+"/Mtr/Sts_FailtoStart") || tag({view.params.Tag}+"/Mtr/Sts_IOFault") || tag({view.params.Tag} + "_Turbo/Error_Status"), "#FF0000",
if(tag({view.params.Tag}+"/Mtr/Sts_FailtoStop") && !tag({view.params.Turbo_Tag}+"/Load_to_On_Timer/DN"), "#FF0000",
if(tag({view.params.Tag}+"/Mtr/Sts_Running") && tag({view.params.Turbo_Tag}+"/Load_Status"), "#72a7fe",
if(tag({view.params.Turbo_Tag}+"/Running_Status") && tag({view.params.Turbo_Tag}+"/Unload_Status"), "#FFFFBF",
if(tag({view.params.Tag}+"/Mtr/Sts_Running"),"#72a7fe","#c0c0c0"
))))))

Yes, definitely. Each one of your tag(...) usages should be changed to an indirect tag binding on a private custom property on the view. Reference the custom properties in your color picking expression.

2 Likes

Thanks, that’s what I thought….

how about scripts vs expressions? Another employee had written this to do the same thing on other equipment.

def determineValveColor(tagPath):
#All valve conditions to check
allTagPaths=[
tagPath + "/Valve/Alm_ActuatorFault",
tagPath + "/Valve/Alm_IOFault",
tagPath + "/Valve/Alm_TransitStall",
tagPath + "/Valve/Alm_FullStall",
tagPath + "/Valve/Alm_IntlkTrip",
tagPath + "/Valve/Sts_Opened",
tagPath + "/Valve/Sts_Closed",
tagPath + "/Valve/Sts_Opening",
tagPath + "/Valve/Sts_Closing",
tagPath + "/Valve/Sts_Available",
tagPath + "/Valve/Sts_Active",
tagPath + "/Valve/Sts_Prog"]

results = system.tag.readBlocking(allTagPaths)

ActFault = results[0].value
IoFault = results[1].value
TransitStall = results[2].value
FullStall = results[3].value
InlkTrip = results[4].value
StsOpen = results[5].value
StsClosed = results[6].value
StsOpening = results[7].value
StsClosing = results[8].value
Available = results[9].value
Active = results[10].value
Program = results[11].value

#Return color to indicate valve state
#if ActFault != null & ActFault:
if ActFault or IoFault or TransitStall or FullStall or InlkTrip:
    return "#FF0000"
if StsOpening or StsClosing:
    return "#FFFFBF"
if Active or StsOpen:
    return "#72a7fe"
if StsClosed or not Active or (not Available and Program):
    return "#c0c0c0"
else:
    return '#000000'`


Scripts are also way slower than indirect bindings on properties.

When possible you want to do direct and indirect bindings to get values and then reference those values wherever you need them.

3 Likes

If you want more control over the update workload, or need to handle a variable list of tag paths, you might find my Integration Toolkit's tags() expression function helpful. (Note the plural.)

1 Like

thanks all. Nothing like learning years too late on a system in production. I have lots fix/change. We were/are having bad performance issues. I think some of this might be part of the problem if I’m reading it right. I just wanted to double check before I got and start changing things.

As well as being terrible performance-wise, such a complicated expression is also a nightmare to test and diagnose if you need to. Having these tags bound to their own custom props lets you easily see their values, and write test values into them to check your logic.

On a side note, the use of “magic” colours here is also poor practice. These should be moved into style classes so that you have globally defined named colours rather than colours copied and pasted throughout the project. Magic colours and values are a maintenance nightmare and are prone to mistakes, inconsistencies, deviations from standards, as well as being incompatible with theming. Ideally you would define your colours inside variables within a custom CSS theme, reference these colour variables within style classes, and then use the style classes within your UI so that your colours are:

  • defined in a single place
  • can be themed
  • can be selected from a dropdown (i.e. the style.classes list)

Sounds like a nightmare of a project to be fixing up :distorted_face:

4 Likes

I had to fix a customer's system that was programmed like this also with tons of expressions using the tag() function. They couldn't even pull up a remote session of the vision client it was so bad. It took time, but once I went through and replaced all of them with bindings, not only were they able to pull up a remote session finally, but everything ran so much faster. (I wonder if it was the same integrator that did yours or if it's just common practice for "newbies" to Ignition to try to tag things like this in an attempt to replicate how FactoryTalk does it)

3 Likes

I think it’s just this. When I started Ignition I used this everywhere too. I still have an old project I work on where I see it used extensively :roll_eyes: I think the issue is that there are so many ways to do things, and there’s not really much in the way of a guide for n00bs (or even intermediate and advanced) to use that warns of poor practices and what to do instead. This forum provides most of this info, but it requires a lot of time and diligence to read topics and posts to sift it out which most people wouldn’t do. I wonder if AI could consolidate the advice across the forum?

Maybe someone needs to write an Ignition For Dummies a Beginner's Guide To Ignition ...

5 Likes

If only there was an Ignition guru on the forum :face_with_hand_over_mouth: I’m sure if there was that he or she would have plenty of spare time!

2 Likes

Bwah, hah, hah!

Here’s what Claude prepared for me. I haven’t looked through it yet… (had to zip as forum doesn’t like docx extensions)

Ignition_Best_Practices_Guide.zip (26.6 KB)

2 Likes

4 Likes

“Do you want me to help you to replace all of your tag bindings with tag() expressions?”

I’m reading through the doc claude produced, and it did a pretty good job tbh. Styling could do with some work… but content is mostly good