[pve-devel] [PATCH proxmox-widget-toolkit v2] form: add Proxmox.form.field.DisplayEdit
Dominik Csapak
d.csapak at proxmox.com
Thu Apr 16 15:19:38 CEST 2020
Looks good except one issue i found,
the 'editConfig' gets modified globally for the class,
leading to weird side effects
i changed the useredit to use this for the username
it worked, but when i created a new user after
editing an old one, the username field was filled
with the last username i edited
the reason is one line in initcomponent (comment inline)
On 4/16/20 2:31 PM, Thomas Lamprecht wrote:
> This allows to write our often used:
>
>> {
>> xtype: me.isCreate ? 'someEditableField' : 'displayfield',
>> ...
>> }
>
> In a more schematic way, as it can now be controlled by either our
> CBind mixin or ExtJS native data binding.
>
> Use a Field container to add both, they editable and they display,
> variants of a form field. As default use "textfield" for the editable
> and "displayfield" xtype for the read only one.
>
> Pass all but the editConfig and editable members of our initial
> config to the display field, allow further to configure the editable
> field with an editConfig object, which overwrites the config
> properties inherited from the displayConfig/parent config.
>
> This gives full control while not enforcing to specify anything extra
> for most default cases.
>
> Enforce initial state of the fields even if the databinding would
> handle it to avoid glitches after first render for simple boolean expression
> cases.
>
>> {
>> xtype: 'pmxDisplayEditField',
>> cbind: {
>> editable: '{isCreate}',
>> },
>> name: 'tokenid',
>> fieldLabel: gettext('Token ID'),
>> value: me.tokenid,
>> allowBlank: false,
>> }
>
> Here, cbind could also be a bind or a native boolean expression.
>
> For something else than a texfield one would use the editConfig, e.g.:
>> {
>> ....
>> editConfig: {
>> xtype: 'pveUserSelector',
>> allowBlank: false,
>> },
>> },
>
> Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
> ---
>
> changes v1 -> v2:
> * fix applying data binding when the instances has it's own bind config already
> * bind value to ensure it's synced between both fields
> * drop array use from "alias" definition, but keep it as ExtJS uses it
> primarily and we too for >3/4 of our definitions
>
> Makefile | 1 +
> form/DisplayEdit.js | 77 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 78 insertions(+)
> create mode 100644 form/DisplayEdit.js
>
> diff --git a/Makefile b/Makefile
> index 703b570..a729b95 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -15,6 +15,7 @@ JSSRC= \
> data/ObjectStore.js \
> data/RRDStore.js \
> data/TimezoneStore.js \
> + form/DisplayEdit.js \
> form/ExpireDate.js \
> form/IntegerField.js \
> form/TextField.js \
> diff --git a/form/DisplayEdit.js b/form/DisplayEdit.js
> new file mode 100644
> index 0000000..f146f91
> --- /dev/null
> +++ b/form/DisplayEdit.js
> @@ -0,0 +1,77 @@
> +Ext.define('Proxmox.form.field.DisplayEdit', {
> + extend: 'Ext.form.FieldContainer',
> + alias: 'widget.pmxDisplayEditField',
> +
> + viewModel: {
> + parent: null,
> + data: {
> + editable: false,
> + value: undefined,
> + },
> + },
> +
> + displayType: 'displayfield',
> +
> + editConfig: {},
> + editable: false,
> + setEditable: function(editable) {
> + let me = this;
> + let vm = me.getViewModel();
> +
> + me.editable = editable;
> + vm.set('editable', editable);
> + },
> +
> + layout: 'hbox',
> + defaults: {
> + hideLabel: true
> + },
> +
> + initComponent: function() {
> + let me = this;
> +
> + let displayConfig = {
> + xtype: me.displayType,
> + bind: {},
> + };
> + Ext.applyIf(displayConfig, me.initialConfig);
> + delete displayConfig.editConfig;
> + delete displayConfig.editable;
> +
> + let editConfig = me.editConfig;
since me.editConfig is an object, this is not a copy,
but a reference
during the second run of initComponent, we get here
the instanced object from before (with all its set values)
what we probably want is a shallow copy
es6 style:
let editConfig = Object.assign({}, me.editConfig);
or extjs style:
let editConfig = Ext.apply({}, me.editConfig);
(we use Ext.apply everywhere, but the es6
style is probably faster, so i included it here
with that change consider it:
Reviewed-By: Dominik Csapak <d.csapak at proxmox.com>
Tested-By: Dominik Csapak <d.csapak at proxmox.com>
> + Ext.applyIf(editConfig, {
> + xtype: 'textfield',
> + bind: {},
> + });
> + Ext.applyIf(editConfig, displayConfig);
> +
> + Ext.applyIf(displayConfig.bind, {
> + hidden: '{editable}',
> + disabled: '{editable}',
> + value: '{value}',
> + });
> + Ext.applyIf(editConfig.bind, {
> + hidden: '{!editable}',
> + disabled: '{!editable}',
> + value: '{value}',
> + });
> +
> + // avoid glitch, start off correct even before viewmodel fixes it
> + editConfig.disabled = editConfig.hidden = !me.editable;
> + displayConfig.disabled = displayConfig.hidden = !!me.editable;
> +
> + editConfig.name = displayConfig.name = me.name;
> +
> + Ext.apply(me, {
> + items: [
> + displayConfig,
> + editConfig,
> + ],
> + });
> +
> + me.callParent();
> +
> + me.getViewModel().set('editable', me.editable);
> + },
> +
> +});
>
More information about the pve-devel
mailing list