Updated Child Table is Not Saved

I have a client script that gets selected rows from a child table and then loops through the child table and sets field “status” to “faulty” whenever one of the selected ones are found (not the most elegeant way, I’m sure).

This works as I expect and the status fields are updated, however when I try to save it says that there are no changes in document and when I reload the changes are missing.

This happens whether I call frm.save() or try to save manually.
NOTE: If I change the field manually I can then save manually. But I don’t understand why it doesn’t recognize the scripted change since I can clearly see that the change has been made in the document.

This is the code, I’m not sure if it will help though since everything works except the saving part.

frappe.ui.form.on("QR Code", "error_report", function(frm, cdt, cdn) {
    let selected = frm.get_selected();
    //console.log(selected);
    
    if(selected.linked_equipment === undefined){
        frappe.msgprint({
            title: __('Error'),
            indicator: 'red',
            message: __('Please select faulty equipment')
        });
    }
    
    else{
        var num_sel = 0;
        selected.linked_equipment.forEach(function(entry){
            num_sel++;
        });
        console.log("num_sel: " + num_sel);

        var BOM_items = frm.doc.linked_equipment;
        BOM_items.forEach(function(entry){
            //console.log("Hej");
            for(let i = 0; i < num_sel; i++){
                console.log("Comparing " + entry.name + " to " + selected.linked_equipment[i]);
                
                // if a match is found
                if (entry.name == selected.linked_equipment[i]){
                  console.log("     Match found!");
                  // set status of item to faulty to be pulled from QR Ticket on creation
                  entry.status = "Faulty";
                    
                }
            }
        });
    
        //create new ticket
        var ticket = frappe.new_doc = ({ 
        	"doctype": "QR Ticket",
            "qr_code": frm.doc.name,
        });
        console.log(ticket);
        //save current form with updated status fields
        frm.save();
        //insert created ticket into database
        frappe.db.insert(ticket);
    }
  
});

Hi @Olle_Olofsson,

I think to use the refresh field after status fields are updated.

cur_frm.save();

Thanks.

Hi @NCP and thank you for the response!

I tried to add this line after each update

refresh_field(entry.status);

So now the updated snippet looks like this

// if a match is found
                if (entry.name == selected.linked_equipment[i]){
                  console.log("     Match found!");
                  // set status of item to faulty to be pulled from QR Ticket on creation
                  entry.status = "Faulty";
                  refresh_field(entry.status);
                    
                }

But it does not make any difference.
Is the syntax incorrect?
Since “entry” is an element in the array of the child table and I can update its value, I think I should be able to use “entry.status” to access the field “status” when I’m refreshing.

I also updated frm.save(); to cur_frm.save();

Thank you.

Hi @Olle_Olofsson,

If refresh for child table field then set like:

cur_frm.refresh_fields('child_table_name');

If refresh for parent field then set like:

cur_frm.refresh_field('parent_field');

Please set your refresh field as you according.

Thanks.

Hello @NCP,
Since I’m updating a field in a child table, I tried your first option

       var BOM_items = frm.doc.linked_equipment;
        BOM_items.forEach(function(entry){
            //console.log("Hej");
            for(let i = 0; i < num_sel; i++){
                console.log("Comparing " + entry.name + " to " + selected.linked_equipment[i]);
                
                // if a match is found
                if (entry.name == selected.linked_equipment[i]){
                  console.log("     Match found!");
                  // set status of item to faulty to be pulled from QR Ticket on creation
                    entry.status = "Faulty";
                    console.log(entry.status);
                    cur_frm.refresh_fields("linked_equipment");
                    
                }
            }
        }

This does not seem to make any difference.

I also console.log(BOM_items[0].status); right before AND right after cur_frm.save();(since my test document only has one item) and the value is correct “Faulty” before and after the save.

Hi @Olle_Olofsson,

the field is updated so what do you want?

Can you explain your process., Please.

Thanks.

Hi @NCP

The problem is that the field is updated in the web form, and

        //save current form with updated status fields
        console.log(BOM_items[0].status);
        cur_frm.save();
        console.log(BOM_items[0].status);

prints

Fualty
Fualty

as it should, but when I try to save with cur_frm.save(); or manually with the “Save” button, I get the message “No changes in document” and if I refresh the page the changes are missing.

If I manually change the status in the UI, it works, but not with the script even though the value has changed in my web form and when I console.log();

I think your document was not updated when the status update.

var BOM_items = frm.doc.linked_equipment;
        BOM_items.forEach(function(entry){
            //console.log("Hej");
            for(let i = 0; i < num_sel; i++){
                console.log("Comparing " + entry.name + " to " + selected.linked_equipment[i]);
                
                // if a match is found
                if (entry.name == selected.linked_equipment[i]){
                  console.log("     Match found!");
                  // set status of item to faulty to be pulled from QR Ticket on creation
                  entry.status = "Faulty";
                  
                  // testing 1
                    cur_frm.refresh_fields("linked_equipment");
                }
            }
            // testing 2
            cur_frm.refresh_fields("linked_equipment");
        });
        // testing 3
        cur_frm.refresh_fields("linked_equipment");

Please try testing step

Something missing a step but doesn’t catch up.

Thanks.

I’ve tested all three isolated and combined but no difference, is it possible to solve with a child table script somehow?

I can set other fields outside the child table just fine and have done so with the following syntax

frm.set_value('field_name', 'data');

Is it possible to use a similar syntax for child table items?

Thanks.

Try it.

I managed to solve it, all I had to do was to call frm.dirty(); before saving so I put it right before I started updating values. It seems I have to call it manually when I’m modifying existing child table items in the client script otherwise ERPNext won’t acknowledge that anything has changed since it doesn’t trigger any pre-defined event as far as I can tell.


https://frappeframework.com/docs/v13/user/en/api/form

Thanks for all the help @NCP !

3 Likes

@Olle_Olofsson,

I think it’s helpful for everyone.

Thanks for giving Solution. :wink:

Thank You!