[FIX] web: allow o2m navigation to work from required inputs
In a one2many, pressing ENTER or TAB from a required input (of type text or char) that is on the last editable column of its line would fail to navigate to next line. The issue was that the validation of the required field would happen before the change to its value was actually applied. This commit fixes it. PR: #26430 Task: 1869469
This commit is contained in:
@@ -114,7 +114,7 @@ var DebouncedField = AbstractField.extend({
|
||||
*/
|
||||
commitChanges: function () {
|
||||
if (this._isDirty && this.mode === 'edit') {
|
||||
this._doAction();
|
||||
return this._doAction();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -135,7 +135,7 @@ var DebouncedField = AbstractField.extend({
|
||||
// do anything (commitChanges ensures that if it has local changes, they
|
||||
// are triggered up before the widget is destroyed, if necessary).
|
||||
if (!this.isDestroyed()) {
|
||||
this._setValue(this._getValue());
|
||||
return this._setValue(this._getValue());
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -1124,6 +1124,14 @@ var FieldX2Many = AbstractField.extend({
|
||||
operation: 'UPDATE',
|
||||
id: ev.data.dataPointID,
|
||||
data: changes,
|
||||
}).done(function () {
|
||||
if (ev.data.onSuccess) {
|
||||
ev.data.onSuccess();
|
||||
}
|
||||
}).fail(function () {
|
||||
if (ev.data.onFailure) {
|
||||
ev.data.onFailure();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -487,22 +487,24 @@ ListRenderer.include({
|
||||
* @private
|
||||
*/
|
||||
_moveToNextLine: function () {
|
||||
var self = this;
|
||||
var record = this.state.data[this.currentRow];
|
||||
var fieldNames = this.canBeSaved(record.id);
|
||||
if (fieldNames.length) {
|
||||
return;
|
||||
}
|
||||
this.commitChanges(record.id).then(function () {
|
||||
var fieldNames = self.canBeSaved(record.id);
|
||||
if (fieldNames.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.currentRow < this.state.data.length - 1) {
|
||||
this._selectCell(this.currentRow + 1, 0);
|
||||
} else {
|
||||
var self = this;
|
||||
this.unselectRow().then(function () {
|
||||
self.trigger_up('add_record', {
|
||||
onFail: self._selectCell.bind(self, 0, 0, {}),
|
||||
if (self.currentRow < self.state.data.length - 1) {
|
||||
self._selectCell(self.currentRow + 1, 0);
|
||||
} else {
|
||||
self.unselectRow().then(function () {
|
||||
self.trigger_up('add_record', {
|
||||
onFail: self._selectCell.bind(self, 0, 0, {}),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
|
||||
@@ -10168,6 +10168,72 @@ QUnit.module('relational_fields', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('one2many with onchange, required field, shortcut enter', function (assert) {
|
||||
assert.expect(5);
|
||||
|
||||
this.data.turtle.onchanges = {
|
||||
turtle_foo: function () {},
|
||||
};
|
||||
|
||||
var def;
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<field name="turtles">' +
|
||||
'<tree editable="bottom">' +
|
||||
'<field name="turtle_foo" required="1"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
mockRPC: function (route, args) {
|
||||
var result = this._super.apply(this, arguments);
|
||||
if (args.method === 'onchange') {
|
||||
return $.when(def).then(_.constant(result));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// simulate what happens in the client:
|
||||
// the new value isn't notified directly to the model
|
||||
fieldDebounce: 5000,
|
||||
});
|
||||
|
||||
var value = "hello";
|
||||
|
||||
// add a new line
|
||||
form.$('.o_field_x2many_list_row_add a').click();
|
||||
|
||||
// we want to add a delay to simulate an onchange
|
||||
def = $.Deferred();
|
||||
|
||||
// write something in the field
|
||||
var $input = form.$('input[name="turtle_foo"]');
|
||||
$input.val(value).trigger('input');
|
||||
|
||||
// trigger keydown ENTER
|
||||
$input.trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
which: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
|
||||
// check that nothing changed before the onchange finished
|
||||
assert.strictEqual($input.val(), value, "input content shouldn't change");
|
||||
assert.strictEqual(form.$('.o_data_row').length, 1,
|
||||
"should still contain only one row");
|
||||
|
||||
// unlock onchange
|
||||
def.resolve();
|
||||
|
||||
// check the current line is added with the correct content and a new line is editable
|
||||
assert.strictEqual(form.$('td.o_data_cell').text(), value);
|
||||
assert.strictEqual(form.$('input[name="turtle_foo"]').val(), '');
|
||||
assert.strictEqual(form.$('.o_data_row').length, 2,
|
||||
"should now contain two rows");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.module('FieldMany2Many');
|
||||
|
||||
QUnit.test('many2many kanban: edition', function (assert) {
|
||||
|
||||
Reference in New Issue
Block a user