Updating records from a repeater

Luca Armienti1
Tera Expert

Hi,

 

I have a repeater that looks somewhat like a survey:

fe_checklist.png

 

UI_builder.png

 

 

The repeater is created with a look-up record data resource.

 

Every item created by the repeater has some input fields, and every item is basically a record in the ServiceNow database. I have to update the records based on the input inserted inside every item when the user click on the save button.

 

My issue is that trying to use Data.look_up_record.results inside a client script, or item.value inside every item, i get the initial value that i got from the lookup, not dynamic; without the input inserted by the user. 

The default way to update data with the UIBuilder is to save the input field Payload.value into client state parameters, and then use the client states for the "update record" operations, but here i have a dynamic number of fields because of the repeater, so i can't do that, i can't create client states for every field i create.

 

So how am I supposed to updating data from a repeater? i tried to find a solution both putting the save button in every item (not optimal) or for all the page, without success.

 

Thanks,

Luca

 

 

2 ACCEPTED SOLUTIONS

Arnoud Kooi
ServiceNow Employee
ServiceNow Employee

As a test, I created below client script.

This can be triggered by any change event of your elements.

 

 

function handler({api, event, helpers, imports}) {

    let elementId = event.elementId;
    let sysId = event.context.item.value._row_data.uniqueValue;
    let value = event.payload.value;

    let updatedData = JSON.parse(JSON.stringify(api.state.updatedData));
    
    let element = updatedData[sysId] || {};
    element[elementId] = value;
    updatedData[sysId] = element;
    api.setState("updatedData", updatedData);
    console.log(updatedData);
    
}

 

 

If you give your elements an id of your field names you could iterate over the object and update the data...

In my test UIB page I have a list of incidents with two elements:

ArnoudKooi_0-1682501259805.png

On every update the client state parameter gets build up:

 

{
    "4045362fdbcb8910f0ff4e68139619a4": {
        "short_description": "RANDOM TESTDATA ",
        "active": true
    },
    "1eaecf121beb3410ba6a437cbc4bcb28": {
        "short_description": "new value"
    }
}

 

When you implement a save button, you can iterate over that object. on update your records

View solution in original post

What i did is:


1) Create an page level event handler on the body, "update_answer", with three properties: fieldName (instead of elementID), itemId(the sysId of the record), value.

customevent1.png

 

 

 

2) Call this event everytime someone select/change value in an input field, and pass the three properties above. 

customevent2.png

customevent2.3.png

 

3) Update the client state parameter with the event handler on the body with a script very similar to yours.

 

let elementId = event.payload.fieldName;
let sysId = event.payload.sysId;
let value = event.payload.value;

let updatedData = JSON.parse(JSON.stringify(api.state.updatedData));

let element = updatedData[sysId] || {};
element[elementId] = value;
updatedData[sysId] = element;
//api.setState("updatedData", updatedData);
console.log(updatedData);
    return {
        propName: 'updatedData',
        value: updatedData
    };

 

customevent3.png

 

4) execute the record update with the event handler on the save button and using the updated client state parameter.

 

I feel better doing it (because of my past experience on other frontend framework) but also: 

event.context.item.value._row_data.uniqueValue;

 

Was not working for me, I couldn't access item.value from context in the component using scripts, while for some reason I can access item with the form.

 

View solution in original post

7 REPLIES 7

Good, I dont think you have access to the values of the elements if you use a page-level event, but I may misunderstand you. Would be curious how you would do that.

I think Luca is talking about creating a custom page event under handled events. That event can be triggered from scripts using api.emit("EVENT_NAME", {PAYLOAD_JSON}); or can be triggered from events directly.

 

 

Jagjeet Singh
ServiceNow Community Rising Star 2022/2023

What i did is:


1) Create an page level event handler on the body, "update_answer", with three properties: fieldName (instead of elementID), itemId(the sysId of the record), value.

customevent1.png

 

 

 

2) Call this event everytime someone select/change value in an input field, and pass the three properties above. 

customevent2.png

customevent2.3.png

 

3) Update the client state parameter with the event handler on the body with a script very similar to yours.

 

let elementId = event.payload.fieldName;
let sysId = event.payload.sysId;
let value = event.payload.value;

let updatedData = JSON.parse(JSON.stringify(api.state.updatedData));

let element = updatedData[sysId] || {};
element[elementId] = value;
updatedData[sysId] = element;
//api.setState("updatedData", updatedData);
console.log(updatedData);
    return {
        propName: 'updatedData',
        value: updatedData
    };

 

customevent3.png

 

4) execute the record update with the event handler on the save button and using the updated client state parameter.

 

I feel better doing it (because of my past experience on other frontend framework) but also: 

event.context.item.value._row_data.uniqueValue;

 

Was not working for me, I couldn't access item.value from context in the component using scripts, while for some reason I can access item with the form.