frappe/datatable

I added an event after field edition, what do you think ?

melBoh opened this issue · 8 comments

Hi !
I needed to save data after inline edition. seeing #46 I thought I should try my hand on it.

It's working for me, but I don't know if it's good enough for community, so, what do you think ?

in apps/frappe/node_modules/frappe-datatable/dist/frappe-datatable.cjs.js
from line 2525
class CellManager { constructor(instance) { this.instance = instance; linkProperties(this, this.instance, [ 'wrapper', 'options', 'style', 'header', 'bodyScrollable', 'columnmanager', 'rowmanager', 'datamanager', 'keyboard', 'fireEvent', //<= add this ]); this.bindEvents();

then, from line 3022

` submitEditing() {
if (!this.$editingCell) return;
const $cell = this.$editingCell;
const {
rowIndex,
colIndex
} = $.data($cell);
const col = this.datamanager.getColumn(colIndex);

    if ($cell) {
        const editor = this.currentCellEditor;

        if (editor) {
            let valuePromise = editor.getValue();

            // convert to stubbed Promise
            if (!valuePromise.then) {
                valuePromise = Promise.resolve(valuePromise);
            }

            valuePromise.then((value) => {
                const done = editor.setValue(value, rowIndex, col);
                const oldValue = this.getCell(colIndex, rowIndex).content;

                // update cell immediately
                this.updateCell(colIndex, rowIndex, value);
                $cell.focus();

                // =>add this : BEGINNING OF add edit submit event
                let rowData = this.datamanager.getData(rowIndex);
                this.fireEvent('onSubmitEditing', [rowData, this.getCell(colIndex, rowIndex).column.id, value]);
                // END OF add edit submit event

                if (done && done.then) {
                    // revert to oldValue if promise fails
                    done.catch((e) => {
                        console.log(e);
                        this.updateCell(colIndex, rowIndex, oldValue);
                    });
                }
            });
        }
    }

    this.currentCellEditor = null;
}`

Then in custom JS (associated to a report in my case)

`
frappe.query_reports["my_report"] = {
...
get_datatable_options(options) {

    // loops on each column and make one ore more of them editable
    options.columns.forEach(function(column, i) {
        // column id i want to make editable
        if(column.id == "your_editable_id") {
            column.editable = true
        }
    });

    // change datatable options
    return Object.assign(options, {
        checkboxColumn: true,
        events: {
            onSubmitEditing: function (cell) {
                // rowValues : all cell values from row before edition
                // cellId : key id of cell edited
                // newVal : edited val
                let [rowValues, cellId, newVal] = cell;
                if(cellId == "your_editable_id") {
                    frappe.call({
                        method: "your.method",
                        type: "GET",
                        args: {name: rowValues.id, qty: newVal}, // for example
                        callback: function (r) {
                            if (r.message) {
                                frappe.msgprint(__(r.message));
                            }
                        },
                    });
                }
            },
        }
    });
},

};

`

Is there any way to get selected rows in Datatable?

But how to get row Ids, that is selected?

What is the Event to capture selected rows?

Thanks in Advance…

@hetal1110 you can get selected rows of report having checkbox as mentioned below:


		onload: function() {
                       // add a button to report
			frappe.query_report.page.add_inner_button(__("Get Selected"), function() {
				var selected_rows = [];
				$('.dt-scrollable').find(":input[type=checkbox]").each((idx, row) => {
					if(row.checked){
						console.log("*** selected row id : " + idx);
						selected_rows.push(frappe.query_report.data[idx]);
					}
				});
			});
		},

Hi @melBoh, thank you very much. I think it's working real well as I have used it to enabled a feature of editing inline and update it in the database. I wonder why it's still not merged to the repository.

If I make the changes on my own, how to prevent the changes be override with next frappe version updates.

why this is still open? Can a PR be made for this?

Actually, I found using the setValue function when setting the datatable's getEditor return object provided the same functionality.

For example (using Frappe Controls)

	getEditor: function(colIndex, rowIndex, value, parent, column, row, data) {
            // colIndex, rowIndex of the cell being edited
            // value: value of cell before edit
            // parent: edit container (use this to append your own custom control)
            // column: the column object of editing cell
            // row: the row of editing cell
            // data: array of all rows

            const control = frappe.ui.form.make_control({
                parent: parent,
                df: {
                    label: '',
                    fieldname: doctype,
                    fieldtype: 'Link',
                    options: doctype
                },
                render_input: true,
                only_input: true,
            });

            let oldValue = '';

            return {
                // called when cell is being edited
                initValue(value) {
                    control.input.focus();
                    control.input.value = value;
                    oldValue = value;
                },
                // called when cell value is set
                setValue(newValue) {
                    // ----------- Do whatever is needed here.
                    control.input.value = newValue;
                },
                // value to show in cell
                getValue() {
                    return control.input.value;
                }
            }
        }

I've hit a strange roadblock.

Inline editing works in Report Builder, but calculated fields are not possible.
Calculated fields are possible in script editor, but inline editing is not possible.

I've hit a strange roadblock.

Inline editing works in Report Builder, but calculated fields are not possible.
Calculated fields are possible in script editor, but inline editing is not possible.

Editing a calculated field goes against their purpose. I would make it whatever type it should be and do the calculation manually. Alternatively, you can make a hidden calculation field and copy the value over to the editable field.

I've hit a strange roadblock.
Inline editing works in Report Builder, but calculated fields are not possible.
Calculated fields are possible in script editor, but inline editing is not possible.

Editing a calculated field goes against their purpose. I would make it whatever type it should be and do the calculation manually. Alternatively, you can make a hidden calculation field and copy the value over to the editable field.

Obviously! I wouldn't want a calculated field to be editable. Instead, I have a report where both type of columns are needed - one for calculated and another for inline editing.