Perspective-openPopup-Accordion

Hello everyone,

I am trying to make an alarm popup that is attached to a view/component (analog indicator for ex) that we already are using the idea is the following:

  • create custom properties on the component that have indirect tag bindings via a udt_path parameter on the component, this is how I will get whether the alarm is true and certain metadata that relates to the alarm etc.
  • If the custom property that is related to the alarm value changes there is a change script that either adds or removes it from an items array.
  • if any alarms on the component are true when you double click the component it will open a popup, that has an accordion in the view, which gets passed the items array custom property of the component on that double click.

The error that I am receiving is that on the double click often times it will have an error saying Error_InvalidPathSyntax root/Accordion.items[2].header.content.text Unable to build tag path, indirection reference(s) [1] did not produce a value.

When I log the items array right before the double click all of the header.content.text values are there. It only happens with the third item in the array and not every time that I click it. I am sure there is something under the hood that I am not aware of with the bindings that is leading this awry.

Thank you for the time

Here is some code

change script for alarm

Summary
    prop = self.custom.alarms.bAlm_H
    updated_items = []
    if (currentValue.value == True):
        item = alarm_popups.makeItem(prop, prop["tagname"], self.view.params.udt_path)
        updated_items = self.custom.items + [item]
    elif (currentValue.value == False):
        updated_items = alarm_popups.removeItem(self.custom.items, prop, prop["tagname"])
    else:
        updated_items = self.custom.items
    sorted_items = sorted(updated_items, key=lambda x: x["severity"], reverse=True)
    self.custom.items = sorted_items

double click event

Summary
    _logger = system.util.getLogger("Alarm Popup Click logger")
    position = {'top':event.pageY,'left':event.pageX}
    popup_id = self.custom.popup_id
    items = self.custom.items
    if(self.custom.in_alarm):
        _logger.info(str(items))
        system.perspective.openPopup(id=popup_id, view="alarm_accordion", position=position, params = {"items": items, "id": popup_id}, showCloseIcon = False, draggable = True)

these are the scripts that I am calling

Summary
def makeItem(alarm_type, tagname, udt):
    item = {"severity": alarm_type["severity"],
            "expanded": False, 
            "header": {
                "content": {
                    "type": "text", 
                    "text": tagname
                }
            },
            "body": {
                "viewPath": "alarm_popup", "viewParams": {
                    "alarm_name": alarm_type["alarm_name"],
                    "parent_path": udt
                }
            }
        }
    return item
    
def removeItem(items, alarm_type, tagname):
    for i, item in enumerate(items):
        if (item["header"]["content"]["text"] == tagname):
            items.pop(i)
    return items

Can you share the actual view of the popup ?
You can copy its json by using shift + right click on the view, in the project browser, then selecting copy json in the contextual menu.
Then you can just paste it here so we can take a look.

popup view JSON

{
"custom": {},
"params": {
"id": "value",
"items":
},
"propConfig": {
"params.id": {
"paramDirection": "input",
"persistent": true
},
"params.items": {
"paramDirection": "input",
"persistent": true
}
},
"props": {
"defaultSize": {
"height": 1000,
"width": 642
}
},
"root": {
"children": [
{
"children": [
{
"events": {
"dom": {
"onClick": {
"config": {
"draggable": true,
"id": "{view.params.id}",
"modal": false,
"overlayDismiss": false,
"resizable": true,
"showCloseIcon": true,
"type": "close",
"viewPath": "",
"viewportBound": false
},
"scope": "C",
"type": "popup"
}
}
},
"meta": {
"name": "Icon"
},
"position": {
"basis": "30px"
},
"props": {
"path": "material/close"
},
"type": "ia.display.icon"
}
],
"meta": {
"name": "FlexContainer"
},
"position": {
"basis": "32px",
"shrink": 0
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Accordion"
},
"position": {
"basis": "300px"
},
"propConfig": {
"props.items": {
"binding": {
"config": {
"path": "view.params.items"
},
"type": "property"
}
},
"props.items[2].header.content.text": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "indirect",
"references": {
"1": "{view.params.udt_path}"
},
"tagPath": "{1}/tagname_1"
},
"type": "tag"
}
}
},
"type": "ia.display.accordion"
},
{
"children": [
{
"meta": {
"name": "Icon_0"
},
"position": {
"basis": "30px"
},
"props": {
"path": "material/autorenew"
},
"type": "ia.display.icon"
}
],
"meta": {
"name": "FlexContainer_0"
},
"position": {
"basis": "32px",
"shrink": 0
},
"props": {
"justify": "flex-end"
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Label"
},
"position": {
"basis": "636px"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.items"
},
"type": "property"
}
}
},
"props": {
"alignVertical": "top"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column"
},
"scripts": {
"customMethods": ,
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "item-update",
"pageScope": true,
"script": "\t# implement your handler here\n\tif (self.view.params.id \u003d\u003d payload["id"]):\n\t\tself.view.params.items \u003d payload["items"]",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.container.flex"
}
}