- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-29-2024 08:43 AM
Seems like a bug related to Data Resources. Here's the scenario:
- I have a "Standard" record page (so we're talking Record Controller).
- I have a subpage loaded into a viewport component on the record page (in the side panel).
- In the subpage, I have a page property defined and bound to @Data.record.form.fields so I can have access to the user interacting with the fields on the form.
- I have a TRANSFORM Data Resource with parameters bound to a Client State param, set to evaluate "Only when invoked".
- I handle the "Page Property Changed" event of the subpage with a script so when the user changes the value of a field on the form, my page property bound to data.record.form.fields will have changed. I only care about a subset of the form fields for my subpage so I only update my client state param if one of those field's changes.
- PROBLEM: My data resource's "Data Fetch Initiated" is firing whenever a user changes ANY field on the form, even when I do not update my client state param that is bound to the DR's inputs. Even when I kill the "Page Property Changed" event handler all together! So the whole "Only when invoked" thing seems to not be working as expected.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-01-2024 08:36 AM
Thanks for the response. In the end, it turned out to be something pretty hidden that I will certainly note going forward. As one does during development, my data resource's parameters went through several iterations before I got them how I wanted them. On the 'Config' tab of my DR in UIB, the parameters showed correctly: all data bound to a client state param object with different attributes. But when I looked at the 'Data' field of my underlying sys_ux_macroponent record for my subpage, I noticed some remnant "inputValues" for my DR, one of them bound to the (sub)page-level property I created that is bound to the "Record" controller's form.fields object. So every time a user changed any form on the field, that property would change and that would cause my DR to refresh.
Seems ServiceNow's UI Builder does not do an amazing job of cleaning up previously entered configurations/code in UIB. So my advice to all is not to rely on what you see in UIB: there may be something hiding!

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-30-2024 10:54 AM - edited ‎03-30-2024 11:03 AM
I feel your pain from the UI Builder / Now Experience learning curve. Through trial and error I figured out a sequence that works for a similar scenario without the server script executing multiple times. Hopefully the scenario I describe gives you enough information to solve your particular issue.
The key for me was not to bind the target component directly to the data resource, but instead bind it to a 2nd client state parameter that serves as an intermediary between the server script and the target field.
If I understand correctly, you have a form with multiple input fields. You'd like the field values to be sent to the server transform script only once, not every time a field changes. Then you'd like to update a client state parameter with the result from the transform script.
I can describe a solution with one text field and a button that has worked for me for just one input field and one "server response" text field. The order of the steps here is the execution order, which differs slightly from the configuration order below.
1. Set `inputText` client state parameter
Configure text area or input component with event handler: "On text area value set, Update client state parameter". New value: @payload.value. This is the event payload from the text area being set and then the user focus moving away from the text field.
2. Trigger data transform script with button click
Configure button with event handler: "On button clicked, run client script". Client script fires the server transform script, passing the client state parameter(s) to the server transform script. The shape/attributes of the `input` object need to be defined on the data broker/transform script record.
Client script:
function handler({api, event, helpers, imports}) {
// Execute the data broker script with the input parameter
// Input object shape defined in data broker / transform script record's properties
// for example, if inputText is defined for the databroker input object,
// and there is a client state parameter inputText:
api.data.<data resource name>.execute({ inputText: api.state.inputText });
}
Property on the data broker record [sys_ux_data_broker_transform]:
[
{
"name": "inputText",
"label": "Input Text",
"description": "Input text to be passed from the client script to the server transform script",
"readOnly": false,
"fieldType": "string",
"mandatory": true,
"defaultValue": ""
}
]
3. Configure data resource linked to the transform script that updates another client state parameter via event handler: In the data resource instance that is associated with the transform script (data broker), set an event handler: "On operation succeeded, Update client state parameter". Let the CSP name be your target client state parameter (for example `serverResponseText`), and let the new value be @payload.data.output, which is the value returned by the transform script. You might need to dot walk to nested attributes if you return JSON rather than just a string.
4. Configure 2nd text field component that has a data binding to CSP #2.
In this case, the data binding value is `
So the execution is
1. Enter text, which updates CSP #1
2. Click button, which triggers client script, which itself triggers the transform script with an input object.
3. When the transform script returns its value to the client, CSP #2 is updated (event handler on the data resource).
4. Data binding to CSP #2 updates the display text in the output text field.
The configuration steps could be:
1. Create two client state parameters, `inputText` and `serverResponseText`.
2. Create data resource of type transform, and configure the Data Broker / server script record as shown above.
3. Create client script as shown above.
4. Configure the input text component with an event handler that sets the `inputText` client state parameter.
5. Configure event handler for the button that triggers the client script, which in turn passes the `inputText` CSP to the transform script.
6. Configure event handler for the data resource that sets the `serverResponseText` CSP after the event 'processing complete'.
7. Set the Text value of the target text field component to have a data binding with the `serverResponseText` CSP.
I found that if I tried to simply set a data binding on the target text field component to the data resource, the transform script would execute with no input. Firing the transform script from the client script upon button click, along with the target field having a data binding to the same transform script/data resource, would result in the transform script executing twice per button click, once from the button event and once from the data binding. So a 2nd client state parameter solves this problem.
Hope that helps!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-01-2024 08:36 AM
Thanks for the response. In the end, it turned out to be something pretty hidden that I will certainly note going forward. As one does during development, my data resource's parameters went through several iterations before I got them how I wanted them. On the 'Config' tab of my DR in UIB, the parameters showed correctly: all data bound to a client state param object with different attributes. But when I looked at the 'Data' field of my underlying sys_ux_macroponent record for my subpage, I noticed some remnant "inputValues" for my DR, one of them bound to the (sub)page-level property I created that is bound to the "Record" controller's form.fields object. So every time a user changed any form on the field, that property would change and that would cause my DR to refresh.
Seems ServiceNow's UI Builder does not do an amazing job of cleaning up previously entered configurations/code in UIB. So my advice to all is not to rely on what you see in UIB: there may be something hiding!

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2024 01:34 PM
Good to know. I experienced similar issues with Mobile App Builder, where the builder UI said one thing but the underlying tables told another story. In UIB, I've found issues when creating variants. A data binding or data resource can look identical to the parent page's configuration in UIB, but it's broken in the clone. If something doesn't work I just recreate the object and then it works again, but probably with references to different records, reducing maintainability. Hopefully plugin updates will resolve these bugs.