[FIX] web: tab selects first many2one entry without triggering spurious create
Suppose you select a customer for a sale order.
You type the beginning of his name "think", and a name_search is triggered
which finds matching results, with first result "Think Big Systems".
There are three ways to select it: click, enter or tab.
Now there can be a warning set on this customer
("Bad client, only accept cash", or "good client, offer discount").
In that case, clicking on tab would trigger the onchange displaying the warning,
but it would also set floating to true, which means a dialog to create client
"think" would appear.
This happens if the onchange is delayed, and thus the call to reset the floating
state is triggered only after the focusout completed, instead of before.
Coauthored with @aab-odoo
opw 1866619
opw 1874475
This commit is contained in:
@@ -578,10 +578,11 @@ var FieldMany2One = AbstractField.extend({
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onInputKeyup: function (ev) {
|
||||
if (ev.which === $.ui.keyCode.ENTER) {
|
||||
// If we pressed enter, we want to prevent _onInputFocusout from
|
||||
if (ev.which === $.ui.keyCode.ENTER || ev.which === $.ui.keyCode.TAB) {
|
||||
// If we pressed enter or tab, we want to prevent _onInputFocusout from
|
||||
// executing since it would open a M2O dialog to request
|
||||
// confirmation that the many2one is not properly set.
|
||||
// It's a case that is already handled by the autocomplete lib.
|
||||
return;
|
||||
}
|
||||
this.isDirty = true;
|
||||
|
||||
@@ -2226,7 +2226,7 @@ QUnit.module('relational_fields', {
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('pressing ENTER on a \'no_quick_create\' many2one should not trigger M2ODialog', function (assert) {
|
||||
QUnit.test('pressing ENTER on a \'no_quick_create\' many2one should open a M2ODialog', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
|
||||
@@ -2277,6 +2277,68 @@ QUnit.module('relational_fields', {
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('select a value by pressing TAB on a many2one with onchange', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(3);
|
||||
|
||||
this.data.partner.onchanges.trululu = function () {};
|
||||
|
||||
var M2O_DELAY = relationalFields.FieldMany2One.prototype.AUTOCOMPLETE_DELAY;
|
||||
relationalFields.FieldMany2One.prototype.AUTOCOMPLETE_DELAY = 0;
|
||||
var def = $.Deferred();
|
||||
|
||||
var form = createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form>' +
|
||||
'<field name="trululu"/>' +
|
||||
'<field name="display_name"/>' +
|
||||
'</form>',
|
||||
mockRPC: function (route, args) {
|
||||
var result = this._super.apply(this, arguments);
|
||||
if (args.method === 'onchange') {
|
||||
return $.when(def).then(_.constant(result));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
res_id: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
|
||||
var $input = form.$('.o_field_many2one input');
|
||||
$input.val("first").trigger('input');
|
||||
concurrency.delay(0).then(function () {
|
||||
var evOptions = {
|
||||
which: $.ui.keyCode.TAB,
|
||||
keyCode: $.ui.keyCode.TAB,
|
||||
};
|
||||
$input.trigger($.Event('keydown', evOptions));
|
||||
$input.trigger($.Event('keypress', evOptions));
|
||||
$input.trigger($.Event('keyup', evOptions));
|
||||
|
||||
// simulate a focusout (e.g. because the user clicks outside)
|
||||
// before the onchange returns
|
||||
form.$('.o_field_char').focus();
|
||||
|
||||
assert.strictEqual($('.modal').length, 0,
|
||||
"there shouldn't be any modal in body");
|
||||
|
||||
// unlock the onchange
|
||||
def.resolve();
|
||||
|
||||
assert.strictEqual($input.val(), 'first record',
|
||||
"first record should have been selected");
|
||||
assert.strictEqual($('.modal').length, 0,
|
||||
"there shouldn't be any modal in body");
|
||||
relationalFields.FieldMany2One.prototype.AUTOCOMPLETE_DELAY = M2O_DELAY;
|
||||
form.destroy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('many2one in editable list + onchange, with enter [REQUIRE FOCUS]', function (assert) {
|
||||
assert.expect(6);
|
||||
var done = assert.async();
|
||||
|
||||
Reference in New Issue
Block a user