Skip to main content

The VertiGIS Community has been moved to the VertiGIS Support Center >>

Refresh form automatically in Workflow 5

Comments

2 comments

  • Alan Lee Clack

    Here's some input based on having a similar set of problems. Hope it helps you or anyone else finding this thread later!

    The first (and abnormally deceptive) issue I had was how to simply infinitely recheck information ideally on a timer. Setting up a Delay loop is easy, but without any way to tell it to be asynchronous I can't get the tool to ever stop, and the logic blocks the entire workflow. As such a simple "update every five seconds" doesn't seem as easily feasible. I haven't found a great way around this yet, but hoping someone knows a way to make Delay asynchronous or some other similar behavior.

    Other than that, updating an ItemPicker has two components in the context I was trying to work with. The first one is just updating the ItemPicker "items" properties which I found easiest with an array of "items" in the basic format of:

    {label:"0", value:0, index:0}

    The first part you may be asking about is updating the ItemPicker after values have changed. On whatever trigger you would like, you can then use the Set Form Element Items activity to set them. My example below uses a ForEach activity to update all items with the Set Property activity, where it updates the label and value appropriately. If you already have an updated item collection you can just reset it with the Set Form Element Items activity. Updating onChange can be similar to a "live" refresh, but you may need to keep in mind the check-states and/or which values differ or need to be transferred over to the new list and/or then organized. This can be done though! It's just a lot of logic I can't throw into a component at the moment. Hopefully some other trigger can be used in your case to get a work around.

     



    I don't have a great way to sandbox anything for VertiGIS, but here is the contents of an exported .json workflow you can play around with to see an "updating" ItemPicker:

    {"_properties":{"isServerWorkflow":false},"components":[{"id":2,"steps":[{"id":3,"inputs":{},"position":"0,0","purpose":"start","title":"Start","transitions":[{"id":7,"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":4},"targetConnector":"top"}]},{"action":"gcx:wf:forms:form:DisplayForm","id":4,"inputs":{"form":{"accessors":[],"code":"resources.forms[values.id]","values":{"id":5}}},"name":"formUpdateItemPicker","position":"-30,90","title":"Display Form"}]},{"id":14,"steps":[{"id":15,"inputs":{},"position":"0,0","purpose":"start","title":"Event","transitions":[{"id":32,"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":31},"targetConnector":"top"}]},{"action":"gcx:wf:core::CreateValue","description":"There is no outside inputs that are dynamic since this is a component, so I create a basic 1, 2, 3, 4, 5, 6 set of \"items\" to start.","id":31,"inputs":{"expression":{"accessors":[],"annotations":[],"code":"[\n    { label: \"0\", value: 0, index: 0 },\n    { label: \"1\", value: 1, index: 1 },\n    { label: \"2\", value: 2, index: 2 },\n    { label: \"3\", value: 3, index: 3 },\n    { label: \"4\", value: 4, index: 4 },\n    { label: \"5\", value: 5, index: 5 }\n]","source":"[\n{label:\"0\", value:0, index:0},\n{label:\"1\", value:1, index:1},\n{label:\"2\", value:2, index:2},\n{label:\"3\", value:3, index:3},\n{label:\"4\", value:4, index:4},\n{label:\"5\", value:5, index:5}\n]"}},"name":"valueInitialArray","position":"-30,90","title":"Initial Loaded Array","transitions":[{"id":274,"position":"90,260 90,290","sourceConnector":"bottom","target":{"id":273},"targetConnector":"top"}]},{"action":"gcx:wf:forms::SetFormElementItems","description":"Set the above array of \"items\" to the ItemPicker.","id":273,"inputs":{"form":{"accessors":["$$form"],"annotations":[{"count":6,"index":0,"kind":"idref"}],"code":"$$form","source":"$$form"},"items":{"accessors":["$valueInitialArray"],"annotations":[{"count":18,"index":0,"kind":"idref"}],"code":"$valueInitialArray.result","source":"$valueInitialArray.result"},"reset":true},"position":"-30,290","title":"Set Form Element Items"}],"title":"load-itemPicker"},{"id":211,"steps":[{"id":212,"inputs":{},"position":"0,0","purpose":"start","title":"Event","transitions":[{"id":341,"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":301},"targetConnector":"top"}]},{"action":"gcx:wf:forms::SetFormElementItems","description":"All of the ItemPicker \"items\" are updated in the above ForEach activity, so we can now replace them. Setting them will update the list for the user as well.","id":299,"inputs":{"elementName":{"accessors":["$formUpdateItemPicker"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$formUpdateItemPicker.state.itemPicker","source":"$formUpdateItemPicker.state.itemPicker"},"form":{"accessors":["$$form"],"annotations":[{"count":6,"index":0,"kind":"idref"}],"code":"$$form","source":"$$form"},"items":{"accessors":["$formUpdateItemPicker"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$formUpdateItemPicker.state.itemPicker.items","source":"$formUpdateItemPicker.state.itemPicker.items"},"reset":true},"position":"-30,370","title":"Set Form Element Items"},{"action":"gcx:wf:core:loop:ForEach","description":"Since there are no dynamic inputs, we simply update each item already in the ItemPicker.\n\nThis is triggered by a manual button as an example.","id":301,"inputs":{"items":{"accessors":["$formUpdateItemPicker"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$formUpdateItemPicker.state.itemPicker.items","source":"$formUpdateItemPicker.state.itemPicker.items"}},"name":"forEachItemPickerItemManual","position":"-30,90","title":"For Each ","transitions":[{"id":307,"inputs":{},"position":"90,340 90,370","sourceConnector":"bottom","target":{"id":299},"targetConnector":"top"}]}],"title":"click-buttonBar"},{"id":281,"steps":[{"action":"gcx:wf:math::Random","id":283,"inputs":{},"name":"randomValueManual","position":"-30,90","title":"Get Random Value","transitions":[{"id":293,"inputs":{},"position":"90,160 90,190","sourceConnector":"bottom","target":{"id":285},"targetConnector":"top"}]},{"action":"gcx:wf:core::SetProperty","description":"Set the **`value`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThe user won't see this, but it is a common property to update.","id":285,"inputs":{"object":{"accessors":["$forEachItemPickerItemManual"],"annotations":[{"count":28,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemManual.item","source":"$forEachItemPickerItemManual.item"},"propertyName":"value","propertyValue":{"accessors":["Math","$randomValueManual"],"annotations":[{"count":4,"index":0,"kind":"idref"},{"count":18,"index":11,"kind":"idref"}],"code":"Math.round($randomValueManual.result * 100)","source":"Math.round($randomValueManual.result*100)"}},"position":"-30,190","title":"Set Property","transitions":[{"id":345,"position":"90,350 90,380","sourceConnector":"bottom","target":{"id":289},"targetConnector":"top"}]},{"id":287,"inputs":{},"position":"0,0","purpose":"start","title":"For Each","transitions":[{"id":295,"inputs":{},"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":283},"targetConnector":"top"}]},{"action":"gcx:wf:core::SetProperty","description":"Set the **`label`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThis string is what the user will in the item picker components and is likely one of the critical components to update.","id":289,"inputs":{"object":{"accessors":["$forEachItemPickerItemManual"],"annotations":[{"count":28,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemManual.item","source":"$forEachItemPickerItemManual.item"},"propertyName":"label","propertyValue":{"accessors":["Math","$randomValueManual"],"annotations":[{"count":4,"index":3,"kind":"idref"},{"count":18,"index":14,"kind":"idref"}],"code":"\"\".concat(Math.round($randomValueManual.result * 100))","source":"`${Math.round($randomValueManual.result*100)}`"}},"position":"-30,380","title":"Set Property"},{"action":"gcx:wf:core::SetProperty","description":"Set the **`label`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThis string is what the user will in the item picker components and is likely one of the critical components to update.","id":342,"inputs":{"object":{"accessors":["$forEachItemPickerItemManual"],"annotations":[{"count":28,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemManual.item","source":"$forEachItemPickerItemManual.item"},"propertyName":"label","propertyValue":{"accessors":["Math","$randomValueManual"],"annotations":[{"count":4,"index":0,"kind":"idref"},{"count":18,"index":11,"kind":"idref"}],"code":"Math.round($randomValueManual.result * 100).toString()","source":"Math.round($randomValueManual.result*100).toString()"}},"position":"240,380","title":"Set Property"},{"action":"gcx:wf:core::Annotation","description":"This is an alternative to building a **`label`** string without backticks (\\`) using the **`.toString()`** method.","id":343,"inputs":{},"position":"240,250","title":"Alternative To Backticks"}]},{"id":308,"steps":[{"id":309,"inputs":{},"position":"0,0","purpose":"start","title":"Event","transitions":[{"id":340,"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":333},"targetConnector":"top"}]},{"action":"gcx:wf:forms::SetFormElementItems","description":"All of the ItemPicker \"items\" are updated in the above ForEach activity, so we can now replace them.\n\nSetting them will update the list for the user as well.","id":331,"inputs":{"form":{"accessors":["$$form"],"annotations":[{"count":6,"index":0,"kind":"idref"}],"code":"$$form","source":"$$form"},"items":{"accessors":["$formUpdateItemPicker"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$formUpdateItemPicker.state.itemPicker.items","source":"$formUpdateItemPicker.state.itemPicker.items"},"reset":true},"position":"-30,370","title":"Set Form Element Items"},{"action":"gcx:wf:core:loop:ForEach","description":"Since there are no dynamic inputs, we simply update each item already in the ItemPicker.\n\nThis is triggered `OnChange` to appear as \"live\" as possible. ","id":333,"inputs":{"items":{"accessors":["$formUpdateItemPicker"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$formUpdateItemPicker.state.itemPicker.items","source":"$formUpdateItemPicker.state.itemPicker.items"}},"name":"forEachItemPickerItemOnChange","position":"-30,90","title":"For Each ","transitions":[{"id":339,"inputs":{},"position":"90,340 90,370","sourceConnector":"bottom","target":{"id":331},"targetConnector":"top"}]}],"title":"change-itemPicker"},{"id":313,"steps":[{"action":"gcx:wf:math::Random","id":315,"inputs":{},"name":"randomValueOnChange","position":"-30,90","title":"Get Random Value","transitions":[{"id":325,"inputs":{},"position":"90,160 90,190","sourceConnector":"bottom","target":{"id":317},"targetConnector":"top"}]},{"action":"gcx:wf:core::SetProperty","description":"Set the **`value`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThe user won't see this, but it is a common property to update.","id":317,"inputs":{"object":{"accessors":["$forEachItemPickerItemOnChange"],"annotations":[{"count":30,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemOnChange.item","source":"$forEachItemPickerItemOnChange.item"},"propertyName":"value","propertyValue":{"accessors":["Math","$randomValueOnChange"],"annotations":[{"count":4,"index":0,"kind":"idref"},{"count":20,"index":11,"kind":"idref"}],"code":"Math.round($randomValueOnChange.result * 100)","source":"Math.round($randomValueOnChange.result*100)"}},"position":"-30,190","title":"Set Property","transitions":[{"id":323,"inputs":{},"position":"90,350 90,380","sourceConnector":"bottom","target":{"id":321},"targetConnector":"top"}]},{"id":319,"inputs":{},"position":"0,0","purpose":"start","title":"For Each","transitions":[{"id":327,"inputs":{},"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":315},"targetConnector":"top"}]},{"action":"gcx:wf:core::SetProperty","description":"Set the **`label`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThis string is what the user will in the item picker components and is likely one of the critical components to update.","id":321,"inputs":{"object":{"accessors":["$forEachItemPickerItemOnChange"],"annotations":[{"count":30,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemOnChange.item","source":"$forEachItemPickerItemOnChange.item"},"propertyName":"label","propertyValue":{"accessors":["Math","$randomValueOnChange"],"annotations":[{"count":4,"index":3,"kind":"idref"},{"count":20,"index":14,"kind":"idref"}],"code":"\"\".concat(Math.round($randomValueOnChange.result * 100))","source":"`${Math.round($randomValueOnChange.result*100)}`"}},"position":"-30,380","title":"Set Property"},{"action":"gcx:wf:core::SetProperty","description":"Set the **`label`** of the ItemPicker \"items\" to a random number (generated above) and altered to be between 1 and 100.\\\nThis string is what the user will in the item picker components and is likely one of the critical components to update.","id":348,"inputs":{"object":{"accessors":["$forEachItemPickerItemManual"],"annotations":[{"count":28,"index":0,"kind":"idref"}],"code":"$forEachItemPickerItemManual.item","source":"$forEachItemPickerItemManual.item"},"propertyName":"label","propertyValue":{"accessors":["Math","$randomValueManual"],"annotations":[{"count":4,"index":0,"kind":"idref"},{"count":18,"index":11,"kind":"idref"}],"code":"Math.round($randomValueManual.result * 100).toString()","source":"Math.round($randomValueManual.result*100).toString()"}},"position":"240,380","title":"Set Property"},{"action":"gcx:wf:core::Annotation","description":"This is an alternative to building a **`label`** string without backticks (\\`) using the **`.toString()`** method.","id":350,"inputs":{},"position":"240,250","title":"Alternative To Backticks"}]}],"deploymentConfig":{"supportedApps":{"GWV":true}},"designerVersion":"5.27.1+8","forms":[{"defaults":{},"elements":{"buttonBar":{"enabled":true,"index":1,"items":{"0":{"index":0,"label":{"markdown":" Manually Refresh ItemPicker"}}},"rowIndex":0,"rowNumber":1,"type":"ButtonBar"},"footer":{"enabled":true,"items":{"0":{"default":true,"index":0,"label":{"markdown":"Close"},"validates":false,"value":"close"}},"section":"footer","type":"ButtonBar"},"header":{"section":"header","title":{"markdown":"Update ItemPicker"},"type":"Header"},"itemPicker":{"enabled":true,"index":2,"prompt":{"markdown":"Filter items"},"rowIndex":0,"rowNumber":2,"selectionMode":"multiple","showFilter":false,"title":{"markdown":"Item Picker"},"type":"ItemPicker"},"text":{"description":{"markdown":"##### **Clicking the Manual Refresh button will refresh the ItemPicker options.**\n ##### **The ItemPicker will also automatically refresh all of its items every time a change is detected.**\nThese triggers are about as \"live\" as I can get until there is a way to asynchronously call a [Delay Activity](https://docs.vertigisstudio.com/workflow/latest/help/Default.htm#wf5/help/activities/delay.htm). Without the asynchronous call, an infinite Delay loop will block an entire workflow indefinitely making it largely unusable. "},"enabled":true,"index":0,"rowIndex":0,"rowNumber":0,"type":"Text"}},"id":5}],"start":{"id":3},"transitions":[{"branch":"load$itemPicker","id":16,"source":{"id":4},"target":{"id":15}},{"branch":"clicked$buttonBar","id":213,"source":{"id":4},"target":{"id":212}},{"branch":"loop","id":303,"inputs":{},"source":{"id":301},"target":{"id":287}},{"branch":"changed$itemPicker","id":310,"source":{"id":4},"target":{"id":309}},{"branch":"loop","id":335,"inputs":{},"source":{"id":333},"target":{"id":319}}]}

     

    Below is the workflow in action if you're able to get it loaded where you can see the items update (in this case just randomly generated numbers to mimic updated data):

    1
  • Zack Robison

    As far as I know, that's something that you're going to need to manage manually in Workflow unless you want to do some custom development.  You might want to contact someone with a bit of WF dev experience to help out with this one.

    In a vacuum, (@..., you might find this interesting) I'd do this by running another workflow (asynchronously) from the item picker's load event. In that workflow, you'll need to run a loop that updates the form element items, then delays for a bit before refreshing again.  If items need to maintain state (like whether they're clicked), be sure to handle it here.  You'll also want something to check that the parent WF still exists so that the updater can exit gracefully.

    In order to update a parent WF's form element items from a child WF, I pass the form from parent to child through the app state with Set/Get App Data activity; and you will need to call $form.actor.refresh() to re-render the form after you've run Set Form Element Items.

    1