Client Script not working On Bulk Submit

Hello Guys

I added a code to Update a field in submit when I submit each form individually it works.

When submitting the docs bulkily from list view the code does not work. Is there any option to work the client script on bulk submit?

Please help me with this.

Thanks in Advance

Does anyone have any solution? Please help me with this

@jinsy The Client Script only works on the specified Doctype. I don’t know anyway to execute a code on bulk update.

Your only option seems Server Script. It should be triggered on bulk update.

@jinsy I have written a workaround code that may help you with bulk update. The problem is that I’m unable to test it myself at the moment, so if you want to try it yourself go ahead but let me know how it goes :grinning:

To test my code, please create a new Client Script, select the Doctype and the select List in the Apply To field, then paste the code and modify the values of the top variables only.

The code will create a new menu action that functions just like the Edit action that is used for bulk update. It will also run the already registered list onload function if it exists.

The variables to modify are:

  1. _doctype which is the name of the Doctype you have selected for the Client Script
  2. _actionButton which is the name of the menu action that will be created, eg: "Edit & Update"
  3. _customFieldsFns which is the list of the custom field names as keys and the modification function for each as values. Each function will receive the doc value that contains the values of the entry that is being updated.
// eg: "Purchase Receipt"
let _doctype = "",
// eg: "Edit & Update"
_actionButton = "",
// eg: {sum_total: function(doc) { return doc.total * 2; }}
_customFieldsFns = {};

// -----------------------------------
// DO NOT EDIT ANYTHING BELOW THIS
// -----------------------------------
let _lvs = frappe.listview_settings[_doctype] = frappe.listview_settings[_doctype] || {},
_pol = _lvs.onload;
_lvs.onload = function(me) {
    if (_pol) _pol(me);
    me.page.add_actions_menu_item(__(_actionButton), () => {
        const is_field_editable = (field_doc) => {
			return (
				field_doc.fieldname &&
				frappe.model.is_value_type(field_doc) &&
				field_doc.fieldtype !== "Read Only" &&
				!field_doc.hidden &&
				!field_doc.read_only &&
				!field_doc.is_virtual
			);
		};
	    let field_mappings = {};
		frappe.meta.get_docfields(me.doctype).forEach((field_doc) => {
			if (is_field_editable(field_doc)) field_mappings[field_doc.label] = Object.assign({}, field_doc);
		});
		me.disable_list_update = true;
		_edit(me.doctype, me.get_checked_items(true), field_mappings,
			() => {
				me.disable_list_update = false;
				me.clear_checked_items();
				me.refresh();
			}
		);
	});
    function _edit(doctype, docnames, field_mappings, done) {
    	let field_options = Object.keys(field_mappings).sort();
    	const status_regex = /status/i;
    	const default_field = field_options.find(value => status_regex.test(value));
    	const dialog = new frappe.ui.Dialog({
    		title: __('Bulk Edit'),
    		fields: [
    			{
    				'fieldtype': 'Select',
    				'options': field_options,
    				'default': default_field,
    				'label': __('Field'),
    				'fieldname': 'field',
    				'reqd': 1,
    				'onchange': () => { set_value_field(dialog); }
    			},
    			{
    				'fieldtype': 'Data',
    				'label': __('Value'),
    				'fieldname': 'value',
    				onchange() { show_help_text(); }
    			}
    		],
    		primary_action: ({ value }) => {
    			const fieldname = field_mappings[dialog.get_value('field')].fieldname;
    			dialog.disable_primary_action();
    			frappe.call({
    				method: 'frappe.desk.doctype.bulk_update.bulk_update.submit_cancel_or_update_docs',
    				args: {
    					doctype: doctype,
    					freeze: true,
    					docnames: docnames,
    					action: 'update',
    					data: {[fieldname]: value || null}
    				}
    			}).then(r => {
    				let failed = r.message || [];
    				if (failed.length && !r._server_messages) {
    					dialog.enable_primary_action();
    					frappe.throw(__('Cannot update {0}', [failed.map(f => f.bold ? f.bold() : f).join(', ')]));
    				}
    				done();
    				dialog.hide();
    				frappe.show_alert({message: __('Updated custom fields'), indicator: 'blue'}, 5);
    				$.each(docnames, function(i, docname) {
    				    frappe.db.get_doc(doctype, docname).then(doc => {
    				        let dt = {};
    				        $.each(_customFieldsFns, function(field, fn) { dt[field] = fn(doc); });
    				        frappe.db.set_value(doctype, docname, dt);
    				    });
    				});
    				frappe.show_alert(__('Updated successfully'));
    			});
    		},
    		primary_action_label: __('Update {0} records', [docnames.length]),
    	});
    	if (default_field) set_value_field(dialog);
    	show_help_text();
    	function set_value_field(dialogObj) {
    		const new_df = Object.assign({}, field_mappings[dialogObj.get_value('field')]);
    		if (new_df.label.match(status_regex) &&
    			new_df.fieldtype === 'Select' && !new_df.default) {
    			let options = [];
    			if (typeof new_df.options === "string") options = new_df.options.split("\n");
    			new_df.default = options[0] || options[1];
    		}
    		new_df.label = __('Value');
    		new_df.onchange = show_help_text;
    		delete new_df.depends_on;
    		dialogObj.replace_field('value', new_df);
    		show_help_text();
    	}
    	function show_help_text() {
    		let value = dialog.get_value('value');
    		if (value == null || value === '') {
    			dialog.set_df_property('value', 'description', __('You have not entered a value. The field will be set to empty.'));
    		} else {
    			dialog.set_df_property('value', 'description', '');
    		}
    	}
    	dialog.refresh();
    	dialog.show();
    }
};
1 Like

Thanks @kid1194 i will try this :slightly_smiling_face:

Is this working?

@crazy_explorer Sorry for my very late reply…

Well, @jinsy should be able to confirm if it’s working or not…

Best regards…