# Controling bindings evaluation order

**URL:** <https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842>\
**Category:** Ignition\
**Tags:** perspective, ignition81\
**Created:** [July 3, 2023, 1:09pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842 "2023-07-03T13:09:02Z")\
**Posts on this page:** 16\
**Page:** 2

<div class="post-metadata">

**Author:** ![j.israelsen](https://avatars.discourse-cdn.com/v4/letter/j/ad7895/32.png) [@j.israelsen](https://forum.inductiveautomation.com/u/j.israelsen)\
**Post date:** [July 3, 2023, 4:00pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/21 "2023-07-03T16:00:04Z")

</div>

Yes, in the code `updateA` and `updateB` would be some type of flag.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 3, 2023, 4:20pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/22 "2023-07-03T16:20:51Z")

</div>

I think I found a way...

dropA: Bound to `params.family_id`  
dropB: expression binding:

```auto
if (isNull(dropA.value),
    null,
    params.category_id
)

```

dropC: expression binding:

```auto
if (isNull(dropB.value),
  null,
  params.item_id
)

```

There's a slight delay, but... it works. And it handles both the initial setup and the reset.  
I'll test it a bit more but it might be enough...

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 3, 2023, 4:27pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/23 "2023-07-03T16:27:43Z")

</div>

Try this:

> **View JSON**
>
> ```auto
> {
> "custom": {
> "isFresh": true
> },
> "params": {
> "category_id": "",
> "family_id": "",
> "item_id": ""
> },
> "propConfig": {
> "custom.isFresh": {
> "access": "PRIVATE",
> "binding": {
> "config": {
> "expression": "coalesce({view.params.family_id}, {view.params.category_id}, {view.params.item_id})"
> },
> "transforms": [
> {
> "expression": "true",
> "type": "expression"
> }
> ],
> "type": "expr"
> },
> "persistent": true
> },
> "params.category_id": {
> "paramDirection": "input",
> "persistent": true
> },
> "params.family_id": {
> "paramDirection": "input",
> "persistent": true
> },
> "params.item_id": {
> "onChange": {
> "enabled": null,
> "script": "\tself.getChild(\"root\").getChild(\"families\").getChild(\"Dropdown\").props.value \u003d self.params.family_id\n\tself.getChild(\"root\").getChild(\"categories\").getChild(\"Dropdown\").props.value \u003d self.params.category_id\n\tself.getChild(\"root\").getChild(\"items\").getChild(\"Dropdown\").props.value \u003d self.params.item_id"
> },
> "paramDirection": "input",
> "persistent": true
> }
> },
> "props": {},
> "root": {
> "children": [
> {
> "children": [
> {
> "events": {
> "component": {
> "onActionPerformed": {
> "config": {
> "params": {},
> "view": "Pascal2"
> },
> "scope": "C",
> "type": "nav"
> }
> }
> },
> "meta": {
> "name": "Button"
> },
> "position": {
> "basis": "80px"
> },
> "props": {
> "text": "Return"
> },
> "type": "ia.input.button"
> },
> {
> "meta": {
> "name": "Label"
> },
> "position": {
> "basis": "100px"
> },
> "propConfig": {
> "props.text": {
> "binding": {
> "config": {
> "path": "view.custom.isFresh"
> },
> "type": "property"
> }
> }
> },
> "type": "ia.display.label"
> }
> ],
> "meta": {
> "name": "return"
> },
> "position": {
> "basis": "50px"
> },
> "type": "ia.container.flex"
> },
> {
> "children": [
> {
> "meta": {
> "name": "Label"
> },
> "position": {
> "basis": "150px"
> },
> "props": {
> "text": "families"
> },
> "type": "ia.display.label"
> },
> {
> "meta": {
> "name": "Dropdown"
> },
> "position": {
> "basis": "256px"
> },
> "propConfig": {
> "props.options": {
> "binding": {
> "config": {
> "queryPath": "sandbox/list_families"
> },
> "type": "query"
> }
> },
> "props.value": {
> "binding": {
> "config": {
> "expression": "if(true, {view.params.family_id}, {this.props.options})"
> },
> "transforms": [
> {
> "code": "\treturn value if self.view.custom.isFresh else None",
> "type": "script"
> }
> ],
> "type": "expr"
> },
> "onChange": {
> "enabled": null,
> "script": "\tif origin \u003d\u003d \u0027Browser\u0027:\n\t\tself.view.custom.isFresh \u003d False"
> }
> }
> },
> "props": {
> "showClearIcon": true
> },
> "type": "ia.input.dropdown"
> },
> {
> "meta": {
> "name": "value"
> },
> "position": {
> "basis": "150px"
> },
> "propConfig": {
> "props.text": {
> "binding": {
> "config": {
> "path": "../Dropdown.props.value"
> },
> "type": "property"
> }
> }
> },
> "type": "ia.display.label"
> }
> ],
> "meta": {
> "name": "families"
> },
> "position": {
> "basis": "34px"
> },
> "props": {
> "style": {
> "gap": "3px"
> }
> },
> "type": "ia.container.flex"
> },
> {
> "children": [
> {
> "meta": {
> "name": "Label"
> },
> "position": {
> "basis": "150px"
> },
> "props": {
> "text": "categories"
> },
> "type": "ia.display.label"
> },
> {
> "meta": {
> "name": "Dropdown"
> },
> "position": {
> "basis": "256px"
> },
> "propConfig": {
> "props.options": {
> "binding": {
> "config": {
> "parameters": {
> "family_id": "{.../families/Dropdown.props.value}"
> },
> "queryPath": "sandbox/list_categories"
> },
> "type": "query"
> }
> },
> "props.value": {
> "binding": {
> "config": {
> "expression": "if(true, {view.params.category_id}, {this.props.options})"
> },
> "transforms": [
> {
> "code": "\treturn value if self.view.custom.isFresh else None",
> "type": "script"
> }
> ],
> "type": "expr"
> },
> "onChange": {
> "enabled": null,
> "script": "\tif origin \u003d\u003d \u0027Browser\u0027:\n\t\tself.view.custom.isFresh \u003d False"
> }
> }
> },
> "props": {
> "showClearIcon": true
> },
> "type": "ia.input.dropdown"
> },
> {
> "meta": {
> "name": "value"
> },
> "position": {
> "basis": "150px"
> },
> "propConfig": {
> "props.text": {
> "binding": {
> "config": {
> "path": "../Dropdown.props.value"
> },
> "type": "property"
> }
> }
> },
> "type": "ia.display.label"
> }
> ],
> "meta": {
> "name": "categories"
> },
> "position": {
> "basis": "34px"
> },
> "props": {
> "style": {
> "gap": "3px"
> }
> },
> "type": "ia.container.flex"
> },
> {
> "children": [
> {
> "meta": {
> "name": "Label"
> },
> "position": {
> "basis": "150px"
> },
> "props": {
> "text": "items"
> },
> "type": "ia.display.label"
> },
> {
> "meta": {
> "name": "Dropdown"
> },
> "position": {
> "basis": "256px"
> },
> "propConfig": {
> "props.options": {
> "binding": {
> "config": {
> "parameters": {
> "category_id": "{.../categories/Dropdown.props.value}"
> },
> "queryPath": "sandbox/list_items"
> },
> "type": "query"
> }
> },
> "props.value": {
> "binding": {
> "config": {
> "expression": "if(true, {view.params.item_id}, {this.props.options})"
> },
> "transforms": [
> {
> "code": "\treturn value if self.view.custom.isFresh else None",
> "type": "script"
> }
> ],
> "type": "expr"
> },
> "onChange": {
> "enabled": null,
> "script": "\tif origin \u003d\u003d \u0027Browser\u0027:\n\t\tself.view.custom.isFresh \u003d False"
> }
> }
> },
> "props": {
> "showClearIcon": true
> },
> "type": "ia.input.dropdown"
> },
> {
> "meta": {
> "name": "value"
> },
> "position": {
> "basis": "150px"
> },
> "propConfig": {
> "props.text": {
> "binding": {
> "config": {
> "path": "../Dropdown.props.value"
> },
> "type": "property"
> }
> }
> },
> "type": "ia.display.label"
> }
> ],
> "meta": {
> "name": "items"
> },
> "position": {
> "basis": "34px"
> },
> "props": {
> "style": {
> "gap": "3px"
> }
> },
> "type": "ia.container.flex"
> }
> ],
> "meta": {
> "name": "root"
> },
> "props": {
> "direction": "column",
> "style": {
> "gap": "10px",
> "padding": "15px"
> }
> },
> "type": "ia.container.flex"
> }
> }
> 
> ```

The only scripts are very simple transforms that check the semaphore. The use of `coalesce()` with the `custom.isFresh` view property is solely to have something that will respond to parameter changes.

Similarly, the `if(true, ...)` expressions for the dropdowns' `props.value` is there purely to monitor changes to the options.

{ You'll have to reset the nav target to the your real project's view name. }

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 3, 2023, 4:33pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/24 "2023-07-03T16:33:39Z")

</div>

Thanks.  
I just tried it and I get the same slight delay.  
Can you see a reason to use one solution over the other ?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 3, 2023, 4:35pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/25 "2023-07-03T16:35:16Z")

</div>

Your solution is not monitoring the options for when the queries deliver the lists.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 3, 2023, 4:38pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/26 "2023-07-03T16:38:11Z")

</div>

Why is this a problem ?  
edit: Yep found it.

edit again: What if I just put a property change script on dropA and dropB options ?  
Or would it be better to hack an options monitoring into my expressions ?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 3, 2023, 5:11pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/27 "2023-07-03T17:11:01Z")

</div>

I strongly prefer bindings over change scripts--usually easier to follow, and they make it hard to forget a return case.

> [@pascal.fragnoud](#):
>
> change script on dropA and dropB options

And you need to monitor the options prop on all three dropdowns.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 3, 2023, 5:26pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/28 "2023-07-03T17:26:27Z")

</div>

The third one is actually a special case that I handle differently, as changes can happen to them that shouldn't trigger a reset.

---

<div class="post-metadata">

**Author:** ![MMaynard](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mmaynard/32/3366_2.png) [@MMaynard](https://forum.inductiveautomation.com/u/MMaynard)\
**Post date:** [July 3, 2023, 6:49pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/29 "2023-07-03T18:49:07Z")

</div>

I would remove all bindings from B and C, then update them with a scripted on Change on A and B.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 3, 2023, 8:04pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/30 "2023-07-03T20:04:49Z")

</div>

How would that work to give them their initial value ?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [July 4, 2023, 6:25am UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/31 "2023-07-04T06:25:47Z")

</div>

how about instead of reseting the values of your dropdown in an onchange script, you reset them in an on action performened event on the dropdowns A and B

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 4, 2023, 6:57am UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/32 "2023-07-04T06:57:11Z")

</div>

I guess it would work. I'll give it a shot, see if it makes things simpler.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [July 4, 2023, 7:26am UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/33 "2023-07-04T07:26:26Z")

</div>

That might be the best solution so far, it's simple and integrates well with some other requirements I have.

Now why the hell didn't anyone think of this sooner ?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [July 4, 2023, 7:44am UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/34 "2023-07-04T07:44:21Z")

</div>

when the crazy js wizard finds a simple solution... xd

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [July 10, 2023, 9:45pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/35 "2023-07-10T21:45:07Z")

</div>

Curios, how would I take the JSON here and create a component with it? It's not a simple copy and paste is it? Nope, that didn't work.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 10, 2023, 10:08pm UTC](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842/36 "2023-07-10T22:08:11Z")

</div>

Shift-right-click on a **view** in the designer tree, then paste. Must be an entire view.

[Previous page](https://forum.inductiveautomation.com/t/controling-bindings-evaluation-order/75842.md?page=1)
