[REF] web: convert FieldBoolean to owl
This commit does 4 things: - adds a file for deprecated legacy fields. - moves legacy FieldBoolean into this file. - converts FieldBoolean to owl component. - adds a new xml file for component fields' templates. task id: 2193996
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// /!\ DEPRECATED
|
||||
//
|
||||
// Legacy Field Widgets are added in this file when they are converted into
|
||||
// Owl Component.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
odoo.define('web.basic_fields.deprecated', function (require) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This module contains most of the basic (meaning: non relational) field
|
||||
* widgets. Field widgets are supposed to be used in views inheriting from
|
||||
* BasicView, so, they can work with the records obtained from a BasicModel.
|
||||
*/
|
||||
|
||||
var AbstractField = require('web.AbstractField');
|
||||
var core = require('web.core');
|
||||
|
||||
var _lt = core._lt;
|
||||
|
||||
var FieldBoolean = AbstractField.extend({
|
||||
className: 'o_field_boolean',
|
||||
description: _lt("Checkbox"),
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
change: '_onChange',
|
||||
}),
|
||||
supportedFieldTypes: ['boolean'],
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Toggle the checkbox if it is activated due to a click on itself.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
activate: function (options) {
|
||||
var activated = this._super.apply(this, arguments);
|
||||
// The formatValue of boolean fields renders HTML elements similar to
|
||||
// the one rendered by the widget itself. Even though the event might
|
||||
// have been fired on the non-widget version of this field, we can still
|
||||
// test the presence of its custom class.
|
||||
if (activated && options && options.event && $(options.event.target).closest('.custom-control.custom-checkbox').length) {
|
||||
this._setValue(!this.value); // Toggle the checkbox
|
||||
}
|
||||
return activated;
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @returns {jQuery} the focusable checkbox input
|
||||
*/
|
||||
getFocusableElement: function () {
|
||||
return this.mode === 'readonly' ? $() : this.$input;
|
||||
},
|
||||
/**
|
||||
* A boolean field is always set since false is a valid value.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
isSet: function () {
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* When the checkbox is rerendered, we need to check if it was the actual
|
||||
* origin of the reset. If it is, we need to activate it back so it looks
|
||||
* like it was not rerendered but is still the same input.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
reset: function (record, event) {
|
||||
var rendered = this._super.apply(this, arguments);
|
||||
if (event && event.target.name === this.name) {
|
||||
this.activate();
|
||||
}
|
||||
return rendered;
|
||||
},
|
||||
/**
|
||||
* Associates the 'for' attribute of the internal label.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
setIDForLabel: function (id) {
|
||||
this._super.apply(this, arguments);
|
||||
this.$('.custom-control-label').attr('for', id);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The actual checkbox is designed in css to have full control over its
|
||||
* appearance, as opposed to letting the browser and the os decide how
|
||||
* a checkbox should look. The actual input is disabled and hidden. In
|
||||
* readonly mode, the checkbox is disabled.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_render: function () {
|
||||
var $checkbox = this._formatValue(this.value);
|
||||
this.$input = $checkbox.find('input');
|
||||
this.$input.prop('disabled', this.mode === 'readonly');
|
||||
this.$el.addClass($checkbox.attr('class'));
|
||||
this.$el.empty().append($checkbox.contents());
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Properly update the value when the checkbox is (un)ticked to trigger
|
||||
* possible onchanges.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onChange: function () {
|
||||
this._setValue(this.$input[0].checked);
|
||||
},
|
||||
/**
|
||||
* Implement keyboard movements. Mostly useful for its environment, such
|
||||
* as a list view.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {KeyEvent} ev
|
||||
*/
|
||||
_onKeydown: function (ev) {
|
||||
switch (ev.which) {
|
||||
case $.ui.keyCode.ENTER:
|
||||
// prevent subsequent 'click' event (see _onKeydown of AbstractField)
|
||||
ev.preventDefault();
|
||||
this.$input.prop('checked', !this.value);
|
||||
this._setValue(!this.value);
|
||||
return;
|
||||
case $.ui.keyCode.UP:
|
||||
case $.ui.keyCode.RIGHT:
|
||||
case $.ui.keyCode.DOWN:
|
||||
case $.ui.keyCode.LEFT:
|
||||
ev.preventDefault();
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
FieldBoolean: FieldBoolean,
|
||||
};
|
||||
|
||||
});
|
||||
@@ -11,6 +11,7 @@ var AbstractField = require('web.AbstractField');
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var datepicker = require('web.datepicker');
|
||||
var deprecatedFields = require('web.basic_fields.deprecated');
|
||||
var dom = require('web.dom');
|
||||
var Domain = require('web.Domain');
|
||||
var DomainSelector = require('web.DomainSelector');
|
||||
@@ -24,6 +25,8 @@ var field_utils = require('web.field_utils');
|
||||
var time = require('web.time');
|
||||
var ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
|
||||
let FieldBoolean = deprecatedFields.FieldBoolean;
|
||||
|
||||
require("web.zoomodoo");
|
||||
|
||||
var qweb = core.qweb;
|
||||
@@ -986,134 +989,6 @@ var FieldMonetary = NumericField.extend({
|
||||
},
|
||||
});
|
||||
|
||||
var FieldBoolean = AbstractField.extend({
|
||||
className: 'o_field_boolean',
|
||||
description: _lt("Checkbox"),
|
||||
events: _.extend({}, AbstractField.prototype.events, {
|
||||
change: '_onChange',
|
||||
}),
|
||||
supportedFieldTypes: ['boolean'],
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Toggle the checkbox if it is activated due to a click on itself.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
activate: function (options) {
|
||||
var activated = this._super.apply(this, arguments);
|
||||
// The formatValue of boolean fields renders HTML elements similar to
|
||||
// the one rendered by the widget itself. Even though the event might
|
||||
// have been fired on the non-widget version of this field, we can still
|
||||
// test the presence of its custom class.
|
||||
if (activated && options && options.event && $(options.event.target).closest('.custom-control.custom-checkbox').length) {
|
||||
this._setValue(!this.value); // Toggle the checkbox
|
||||
}
|
||||
return activated;
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @returns {jQuery} the focusable checkbox input
|
||||
*/
|
||||
getFocusableElement: function () {
|
||||
return this.mode === 'readonly' ? $() : this.$input;
|
||||
},
|
||||
/**
|
||||
* A boolean field is always set since false is a valid value.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
isSet: function () {
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* When the checkbox is rerendered, we need to check if it was the actual
|
||||
* origin of the reset. If it is, we need to activate it back so it looks
|
||||
* like it was not rerendered but is still the same input.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
reset: function (record, event) {
|
||||
var rendered = this._super.apply(this, arguments);
|
||||
if (event && event.target.name === this.name) {
|
||||
this.activate();
|
||||
}
|
||||
return rendered;
|
||||
},
|
||||
/**
|
||||
* Associates the 'for' attribute of the internal label.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
setIDForLabel: function (id) {
|
||||
this._super.apply(this, arguments);
|
||||
this.$('.custom-control-label').attr('for', id);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The actual checkbox is designed in css to have full control over its
|
||||
* appearance, as opposed to letting the browser and the os decide how
|
||||
* a checkbox should look. The actual input is disabled and hidden. In
|
||||
* readonly mode, the checkbox is disabled.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_render: function () {
|
||||
var $checkbox = this._formatValue(this.value);
|
||||
this.$input = $checkbox.find('input');
|
||||
this.$input.prop('disabled', this.mode === 'readonly');
|
||||
this.$el.addClass($checkbox.attr('class'));
|
||||
this.$el.empty().append($checkbox.contents());
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Properly update the value when the checkbox is (un)ticked to trigger
|
||||
* possible onchanges.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onChange: function () {
|
||||
this._setValue(this.$input[0].checked);
|
||||
},
|
||||
/**
|
||||
* Implement keyboard movements. Mostly useful for its environment, such
|
||||
* as a list view.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {KeyEvent} ev
|
||||
*/
|
||||
_onKeydown: function (ev) {
|
||||
switch (ev.which) {
|
||||
case $.ui.keyCode.ENTER:
|
||||
// prevent subsequent 'click' event (see _onKeydown of AbstractField)
|
||||
ev.preventDefault();
|
||||
this.$input.prop('checked', !this.value);
|
||||
this._setValue(!this.value);
|
||||
return;
|
||||
case $.ui.keyCode.UP:
|
||||
case $.ui.keyCode.RIGHT:
|
||||
case $.ui.keyCode.DOWN:
|
||||
case $.ui.keyCode.LEFT:
|
||||
ev.preventDefault();
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
var FieldInteger = NumericField.extend({
|
||||
description: _lt("Integer"),
|
||||
className: 'o_field_integer o_field_number',
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
odoo.define('web.basic_fields_owl', function (require) {
|
||||
"use strict";
|
||||
|
||||
const AbstractField = require('web.AbstractFieldOwl');
|
||||
const CustomCheckbox = require('web.CustomCheckbox');
|
||||
const core = require('web.core');
|
||||
|
||||
const _lt = core._lt;
|
||||
|
||||
class FieldBoolean extends AbstractField {
|
||||
patched() {
|
||||
super.patched();
|
||||
if (this.props.event && this.props.event.target === this) {
|
||||
this.activate();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Public
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @returns {HTMLElement|null} the focusable checkbox input
|
||||
*/
|
||||
get focusableElement() {
|
||||
return this.mode === 'readonly' ? null : this.el.querySelector('input');
|
||||
}
|
||||
/**
|
||||
* A boolean field is always set since false is a valid value.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
get isSet() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Toggle the checkbox if it is activated due to a click on itself.
|
||||
*
|
||||
* @override
|
||||
* @param {Object} [options]
|
||||
* @param {Event} [options.event] the event which fired this activation
|
||||
* @returns {boolean} true if the component was activated, false if the
|
||||
* focusable element was not found or invisible
|
||||
*/
|
||||
activate(options) {
|
||||
const activated = super.activate(options);
|
||||
// The event might have been fired on the non field version of
|
||||
// this field, we can still test the presence of its custom class.
|
||||
if (activated && options && options.event && options.event.target
|
||||
.closest('.custom-control.custom-checkbox')) {
|
||||
this._setValue(!this.value); // Toggle the checkbox
|
||||
}
|
||||
return activated;
|
||||
}
|
||||
/**
|
||||
* Associates the 'for' attribute of the internal label.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
setIdForLabel(id) {
|
||||
super.setIdForLabel(id);
|
||||
this.el.querySelector('label').setAttribute('for', id);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Handlers
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Properly update the value when the checkbox is (un)ticked to trigger
|
||||
* possible onchanges.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onChange(ev) {
|
||||
this._setValue(ev.target.checked);
|
||||
}
|
||||
/**
|
||||
* Implement keyboard movements. Mostly useful for its environment, such
|
||||
* as a list view.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {KeyEvent} ev
|
||||
*/
|
||||
_onKeydown(ev) {
|
||||
switch (ev.which) {
|
||||
case $.ui.keyCode.ENTER:
|
||||
// prevent subsequent 'click' event (see _onKeydown of AbstractField)
|
||||
ev.preventDefault();
|
||||
this._setValue(!this.value);
|
||||
return;
|
||||
case $.ui.keyCode.UP:
|
||||
case $.ui.keyCode.RIGHT:
|
||||
case $.ui.keyCode.DOWN:
|
||||
case $.ui.keyCode.LEFT:
|
||||
ev.preventDefault();
|
||||
}
|
||||
super._onKeydown(ev);
|
||||
}
|
||||
}
|
||||
FieldBoolean.components = { CustomCheckbox };
|
||||
FieldBoolean.description = _lt("Checkbox");
|
||||
FieldBoolean.supportedFieldTypes = ['boolean'];
|
||||
FieldBoolean.template = 'web.FieldBoolean';
|
||||
|
||||
return {
|
||||
FieldBoolean,
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="web.FieldBoolean" owl="1">
|
||||
<CustomCheckbox disabled="mode === 'readonly'" value="value"
|
||||
class="o_field_boolean" t-on-change="_onChange"/>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
Reference in New Issue
Block a user