extJS. Destroy и Render полей формы

Здравия.

У меня есть форма, в которой используются свои combobox-ы. Надо при выборе в первом select-е подгружать данные из базы во второе в зависимости от выбранного варианта в первом. С подгрузкой мне помог Сергей. Мне удалось сделать так, чтобы при выборе в первом поле во второе подгружались нужные варианты выбора. Однако если мы первый раз подгрузили в это поле данные, то второй раз они внешне никак не обновляются, хотя значения обновляются. Я так понял для этого надо разрушить и отрендерить поле заново. А вот как это сделать? Я получил нужное поле при событии select в первом Ext.getCmp( config.id +'-version'), выполняю в нём метод destroy(), а далее он уже не выполняет метод render(). Поле не появляется.

Вот код моих полей в форме:
{
	xtype: 'hostpanel-combo-cms',
	fieldLabel: _('hostpanel_site_cms'),
	name: 'cms',
	id: config.id +'-cms',
	anchor: '100%',
	listeners: {
		'select': {
			fn: function (o) {
				var hostpanel_combo_version = Ext.getCmp( config.id +'-version');
				
				hostpanel_combo_version.store = new Ext.data.JsonStore({
					id: 0,
					root: 'results',
					totalProperty: 'total',
					autoLoad: true,
					fields: ['value', 'display'],
					url: hostPanel.config.connector_url,
					baseParams: {
						action: 'mgr/settings/getlist',
						key: 'version',
						parent: o.value,
					},
				});
				
				hostpanel_combo_version.destroy();
				setTimeout(function(){
					hostpanel_combo_version.render();
				},1000);
			}, scope:this
		},
	},
}, {
	xtype: 'hostpanel-combo-version',
	fieldLabel: _('hostpanel_site_version'),
	name: 'version',
	id: config.id +'-version',
	anchor: '100%',
}
Павел Гвоздь
06 ноября 2015, 09:58
modx.pro
2
3 200
0
Поблагодарить автора Отправить деньги

Комментарии: 12

Сергей Шлоков
06 ноября 2015, 20:20
+1
Подход абсолютно не правильный. Ничего удалять не надо. У каждого комбобокса есть store. Нужно для store второго комбобокса указать выбранное значение в качестве параметра baseParams, а в его getlist процессоре учитывать этот параметр для ограничения запроса. Затем перечитать store.load().
Дал направление для самостоятельной попытки. Если не получится, пиши.
    Павел Гвоздь
    06 ноября 2015, 20:39
    0
    Пишу вот такую штуку в то же событие select:
    {
    	xtype: 'hostpanel-combo-cms',
    	fieldLabel: _('hostpanel_site_cms'),
    	name: 'cms',
    	id: config.id +'-cms',
    	anchor: '100%',
    	listeners: {
    		'select': {
    			fn: function (o) {
    				var hostpanel_combo_version = Ext.getCmp( config.id +'-version');
    				
    				hostpanel_combo_version.store.load( hostpanel_combo_version.store, new Ext.data.JsonStore({
    					id: 0,
    					root: 'results',
    					totalProperty: 'total',
    					autoLoad: true,
    					fields: ['value', 'display'],
    					url: hostPanel.config.connector_url,
    					baseParams: {
    						action: 'mgr/settings/getlist',
    						key: 'version',
    						parent: o.value,
    					},
    				}) );
    				
    			}, scope:this
    		},
    	},
    }, {
    	xtype: 'hostpanel-combo-version',
    	fieldLabel: _('hostpanel_site_version'),
    	name: 'version',
    	id: config.id +'-version',
    	anchor: '100%',
    }

    GetList процессор у меня уже обрабатывает ограничения по полю parent на основании value.o (значения, выбранного в первом combobox-е). Даже больше — он отдаёт в ExtJS нужные мне данные. Только вот отобразить во втором combobox-е я их пока не могу.
      Павел Гвоздь
      06 ноября 2015, 21:01
      0
      Сергей, вот смотри. Я вот этим кодом могу обновлять значения в combobox-е, только он внешне пункты при выпадении вариантов выбора не обновляет:
      hostpanel_combo_version.store = new Ext.data.JsonStore({
      	id: 0,
      	root: 'results',
      	totalProperty: 'total',
      	autoLoad: true,
      	fields: ['value', 'display'],
      	url: hostPanel.config.connector_url,
      	baseParams: {
      		action: 'mgr/settings/getlist',
      		key: 'version',
      		parent: o.value,
      	},
      });

      Получается вот так:


      Тут я кликаю на выпавший пункт, а он мне показывает выбранным совсем другой, тот, который подгрузил мне GetList.
        Сергей Шлоков
        06 ноября 2015, 22:41
        +1
        Если понять принцип работы компонентов, то все становится просто
        'select': {
        	fn: function (o) {
        		var hostpanel_combo_version = Ext.getCmp( config.id +'-version'),
        			store = hostpanel_combo_version.store;
        		// Удаляем старые записи из комбобокса
        		store.removeAll();
        		// Прописываем нужный параметр для getlist процессора
        		store.baseParams['parent'] = o.value;
        		// Зачитываем новые записи
        		store.load();
        		// Очищаем поле комбобокса
        		hostpanel_combo_version.setValue('');
        	}, scope:this
        }
          Павел Гвоздь
          06 ноября 2015, 22:43
          0
          Спасибо, Сергей, тебе огроменное! Это работает! Очень жду очередную твою статью по ExtJS! :)
            Сергей Шлоков
            06 ноября 2015, 22:50
            +1
            Велком!
              Павел Гвоздь
              07 ноября 2015, 19:59
              0
              Сергей, если не затруднит, подскажи пожалуйста.

              Я создаю свой комбобокс, мне надо, чтоб при выборе отображался один текст, а на сервер уходили только значения. Вот код комбобокса:
              hostPanel.combo.version = function(config) {
              	config = config || {};
              	Ext.applyIf(config, {
              		store: new Ext.data.JsonStore({
              			id: 0,
              			root: 'results',
              			totalProperty: 'total',
              			autoLoad: true,
              			fields: ['value', 'display'],
              			url: hostPanel.config.connector_url,
              			baseParams: {
              				action: 'mgr/settings/getlist',
              				key: 'version',
              			},
              			listeners: {
              				'clear': { fn: function(obj) { this.hide(); }, scope:this },
              				'load': { fn: function(obj, recs, opts) { obj.getTotalCount() > 0 && this.show(); }, scope:this },
              			},
              		}),
              		mode: 'local',
              		displayField: 'display',
              		value: 'value',
              		valueField: 'value',
              		typeAhead: true,
              		triggerAction: 'all',
              	});
              	hostPanel.combo.version.superclass.constructor.call(this,config);
              };
              Ext.extend(hostPanel.combo.version, MODx.combo.ComboBox);
              Ext.reg('hostpanel-combo-version', hostPanel.combo.version);

              Проблема в том, что на сервер уходит текст displayField: 'display', а не значение valueField: 'value'. В доках смотрел и не нашёл такого параметра. Может ты знаешь, как это решить?

              P.S.: Если в displayField подставляем 'value', то сохраняет правильно. Но так не надо.
                Сергей Шлоков
                07 ноября 2015, 21:49
                +1
                У комбобокса, как и у любого поля формы, должно быть имя — атрибут name, а также hiddenName. Они должны совпадать друг с другом. А для зачитки данных с сервера нужно указать mode: 'remote'.
                  Павел Гвоздь
                  08 ноября 2015, 01:47
                  +1
                  Спасибо, Сергей! Сначало не понял, вроде указал поле name, думал этого достаточно. Не понимал, при чём тут hiddenName. Когда подставил — всё получилось. Никогда бы не подумал, что этот параметр мне поможет. Спасибо ещё раз, Сергей, ты мне очень помог!
        Павел Гвоздь
        06 ноября 2015, 22:39
        0
        Удалось решить вот так:
        {
        	xtype: 'hostpanel-combo-cms',
        	fieldLabel: _('hostpanel_site_cms'),
        	name: 'cms',
        	id: config.id +'-cms',
        	anchor: '100%',
        	listeners: {
        		'select': {
        			fn: function (o) {
        				var hostpanel_combo_version = Ext.getCmp( config.id +'-version');
        				
        				hostpanel_combo_version.reset();
        				
        				hostpanel_combo_version.store = new Ext.data.JsonStore({
        					id: 0,
        					root: 'results',
        					totalProperty: 'total',
        					autoLoad: true,
        					fields: ['value', 'display'],
        					url: hostPanel.config.connector_url,
        					baseParams: {
        						action: 'mgr/settings/getlist',
        						key: 'version',
        						parent: o.value,
        					},
        				});
        				
        				hostpanel_combo_version.bindStore( hostpanel_combo_version.getStore() );
        				
        			}, scope:this
        		},
        	},
        }, {
        	xtype: 'hostpanel-combo-version',
        	fieldLabel: _('hostpanel_site_version'),
        	name: 'version',
        	id: config.id +'-version',
        	anchor: '100%',
        }

        Только теперь, если не кликнул на второе поле перед тем, как выбрал что-нибудь в первом, в консоли вылазит вот такая ошибка:


        И вылазит до тех пор, пока не кликнем на втором поле. Не знаешь, что на это влияет?
          Алексей Шумаев
          16 июля 2017, 13:08
          0
          Павел, не выяснилось в чём была проблема с «Cannot read property 'setWidth' of undefined»?
          Учусь на этом примере, то же самое вылезло, что не удивительно )
          Работает всё нормально.
            Павел Гвоздь
            17 июля 2017, 07:21
            +1
            Решить удалось, но переписав все по иному. Сейчас бы сделал все гораздо иначе и правильнее. :)
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        12