Ext JS - привязать несколько полей формы к одному полю модели

У меня есть модель с шестнадцатеричным цветовым полем. Пользователь может редактировать его как rgb через 3 отдельных числовых поля. Я пытаюсь связать поле с этими компонентами, но не знаю, как это сделать. Я попытался поместить их в контейнер и привязать контейнер к полю. Однако мой setValue не вызывается при изменении числового поля.

Думаю, я мог бы добавить слушателей к числовым полям, но я надеялся, что есть лучший способ сделать это.

https://fiddle.sencha.com/#view/editor&fiddle/23t2


person DrRumpus    schedule 25.07.2017    source источник


Ответы (2)


setValue вызывается только в поле формы. Поля формы обозначаются конфигом isFormField: true. Однако обратите внимание, что setValue — не единственная функция, ожидаемая от поля формы; есть десятки других (например, getValue, getModelValue, isValid, ...).

Из-за этого я всегда использую hiddenfield для агрегирования других полей формы, а не container, а затем я использую прослушиватели изменений для синхронизации скрытого поля и других полей (bind тоже должен работать, но наше приложение по-прежнему MVC). Я также комментирую другие поля с помощью

excludeForm: true,
submitValue: false,

чтобы убедиться, что значения не отправляются и не влияют на «грязное» состояние формы.

person Alexander    schedule 25.07.2017
comment
Спасибо за ответ. Я переключился на «скрытое поле», но я действительно не уверен, как связать с ним числовые поля. Не могли бы вы показать пример? fiddle.sencha.com/#view/editor&fiddle/23t4 - person DrRumpus; 25.07.2017

Я внес некоторые изменения. Это будет работать для обоих сценариев,

  1. если пользователь изменит имя цвета (textfield), тогда RGB изменится.
  2. Если пользователь изменит числовое поле, имя цвета (textfield) будет изменено.

Попробуйте этот код в своей сенче скрипке.

Ext.create({
    xtype: 'viewport',
    renderTo: Ext.getBody(),

    viewModel: {
        data: {
            theColor: {
                name: 'Blue',
                hex: '3366CC'
            }
        },
        formulas: {
            containerValue: {
                bind: '{theColor.hex}',
                get: function (value) {
                    return {
                        hex: value
                    };
                },
                set: function (value) {
                    this.set('theColor.hex', value.hex);
                }
            }
        }
    },

    items: [{
        region: 'center',
        xtype: 'form',
        bodyPadding: 10,
        height: 300,

        fieldDefaults: {
            labelWidth: 90,
        },

        items: [{
            xtype: 'component',
            width: 30,
            height: 30,
            bind: {
                style: {
                    background: '#{theColor.hex}'
                }
            }
        }, {
            xtype: 'textfield',
            fieldLabel: 'Name',
            bind: '{theColor.name}',
            listeners:{
                blur:function(textfield,e,eOpts){
                    var viewModel = textfield.up('viewport').getViewModel();
                        colorName = textfield.getValue(),
                        hex = colorToHex(colorName);
                    viewModel.set('theColor',{
                     name: colorName,
                     hex: hex
                    });
                    function colorToRGBA(color) {
                        // Returns the color as an array of [r, g, b, a] -- all range from 0 - 255
                        // color must be a valid canvas fillStyle. This will cover most anything
                        // you'd want to use.
                        // Examples:
                        // colorToRGBA('red')  # [255, 0, 0, 255]
                        // colorToRGBA('#f00') # [255, 0, 0, 255]
                        var cvs, ctx;
                        cvs = document.createElement('canvas');
                        cvs.height = 1;
                        cvs.width = 1;
                        ctx = cvs.getContext('2d');
                        ctx.fillStyle = color;
                        ctx.fillRect(0, 0, 1, 1);
                        return ctx.getImageData(0, 0, 1, 1).data;
                    }

                    function byteToHex(num) {
                        // Turns a number (0-255) into a 2-character hex number (00-ff)
                        return ('0'+num.toString(16)).slice(-2);
                    }

                    function colorToHex(color) {
                        // Convert any CSS color to a hex representation
                        // Examples:
                        // colorToHex('red')            # '#ff0000'
                        // colorToHex('rgb(255, 0, 0)') # '#ff0000'
                        var rgba, hex;
                        rgba = colorToRGBA(color);
                        hex = [0,1,2].map(
                            function(idx) { return byteToHex(rgba[idx]); }
                            ).join('');
                        return hex;
                    }
                }
            }
        }, {
            xtype: 'container',

            setValue: function (value) {
                const hex = value.hex || '000000';

                const red = parseInt(hex.substr(0, 2), 16);
                const green = parseInt(hex.substr(2, 2), 16);
                const blue = parseInt(hex.substr(4, 2), 16);

                const items = this.query('');

                items[0].setValue(red);
                items[1].setValue(green);
                items[2].setValue(blue);
            },

            bind: {
                value: '{containerValue}',
            },

            defaults: {
                xtype: 'numberfield',
                maxValue: 255,
                minValue: 0,
                allowBlank: false,
                width: 175,
                listeners:{
                    change:function(numberfield){
                        if(numberfield.hasFocus){
                            var viewModel = numberfield.up('viewport').getViewModel(),
                                items = this.up().query(''),
                                red =  items[0].getValue() || 0,
                                green = items[1].getValue() || 0,
                                blue = items[2].getValue() || 0,
                                hex = rgbToHex(red,green,blue);
                            viewModel.set('theColor',{
                             name: hex,//For hex to color name you have to search for that, here I am giving hax color.
                             hex: hex
                            });
                            function componentToHex(c) {
                                var hex = c.toString(16);
                                return hex.length == 1 ? "0" + hex : hex;
                            }

                            function rgbToHex(r, g, b) {
                                return componentToHex(r) + componentToHex(g) + componentToHex(b);
                            }
                        }
                    }
                }
            },

            items: [{
                fieldLabel: 'R',
            }, {
                fieldLabel: 'G',
            }, {
                fieldLabel: 'B',
            }]
        }]
    }]
});
person Narendra Jadhav    schedule 25.07.2017