Implement MVC
In this example we’ll split up our code using ExtJS 4 MVC (Model View Controller) framework. De-coupling our models, views, and controllers makes the code very easy to modify later. This will come in handy when we have to add various input types later. Also, we will now be able to clone our fieldset with very little code:
JS
... // Create 2 fieldsets Ext.create('Ext.container.Container',{ renderTo: Ext.getBody() , defaults: { xtype: 'mc_fieldsetdynamiccontrols' , margin: 10 } , items: [ { title: 'Search Filter 1' } , { title: 'Search Filter 2' } ] }); ... |
JS – Model
I used to be lazy and avoided using models – I’d define them inside the store. Since then I’ve learned that splitting off a model always pays off!
... // Represents an input on the fieldset Ext.define('MyCompany.model.FieldsetDynamicControls', { extend: 'Ext.data.Model' , fields: ['name','label'] }); // Possible inputs Ext.namespace('MyCompany.globals.FieldsetDynamicControls'); MyCompany.globals.FieldsetDynamicControls.possibleValues = [ { label: 'Display Name', name: 'displayName' } , { label: 'First Name', name: 'givenName' } , { label: 'Middle Name', name: 'initials' } , { label: 'Last Name', name: 'sn' } ]; ... |
JS – View
Here we basically take our custom fieldset from previous examples, and wrap it in extension of the standard FieldSet; notice code where we implement custom events ‘addcontrol’ and ‘removecontrol’:
... Ext.define('MyCompany.view.FieldsetDynamicControls', { extend: 'Ext.form.FieldSet' , alias: 'widget.mc_fieldsetdynamiccontrols' // xtype == mc_fieldsetdynamiccontrols , initComponent: function () { var me = this; me.addEvents('addcontrol','removecontrol'); var config = { title: 'Search Filter' , width: 300 , collapsible: true , iconCls: 'icon-properties' , style: 'background-color: #F1F1F1;' + 'position: relative;' // support the [+] button , items: [ { // [Add] button with dropdown menu xtype: 'button' , style: 'position: absolute; top: ' +(Ext.isIE||Ext.isChrome?0:-20) + 'px; right: 20px;' , iconCls: 'icon-add' // drop-down menu , menu: Ext.create('Ext.menu.Menu', { plain: true , items: [ { html: '<b>Attribute</b>' } , { xtype: 'combo' , queryMode: 'local' , displayField: 'label' , valueField: 'name' , typeAhead: true , allowBlank: false , store: Ext.create('Ext.data.Store', { model:'MyCompany.model.FieldsetDynamicControls' , data:MyCompany.globals.FieldsetDynamicControls.possibleValues , sorters: [ { property: 'label' } ] }) // eo store } // eo combo ] // eo items , bbar: [ '->', { xtype: 'button' , iconCls: 'icon-add' , text: 'Add' , handler: function() { // Fire custom event me.fireEvent('addcontrol',me); } } ] }) // eo Menu } // eo [Add] button with dropdown menu , { xtype: 'textfield' , fieldLabel: 'Test' , msgTarget: 'under' , allowBlank: false , anchor: '-25' , listeners : { // Add "remove" button afterrender: function(tf) { var el = tf.bodyEl.createChild({tag: 'div', style:'position: absolute; right: -23px; top: 0px;'}); tf.innerButton = Ext.create('Ext.button.Button',{ renderTo: el , iconCls: 'icon-remove' , handler: function() { // Fire custom event me.fireEvent('removecontrol',me); } }); } // Our button does not get destroyed when we // destroy the parent textfield or the parent fieldset , destroy: function(tf) { tf.innerButton.destroy(); } } // eo listeners } // eo textfield ] // eo items }; // eo config object // apply config Ext.apply(me, Ext.applyIf(me.initialConfig, config)); me.callParent(arguments); } // eo function initComponent }); ... |
JS – Controller
In this kind of custom controls, you do not always want to implement a controller, for sake of not forcing the consumer to have to register it (see below in the On Ready section).
... Ext.define("MyCompany.controller.FieldsetDynamicControls", { extend: "Ext.app.Controller" , init: function() { var controller = this; controller.control({ 'mc_fieldsetdynamiccontrols' : { addcontrol: function(fieldset) { controller.addControl(fieldset); } , removecontrol: function(fieldset) { controller.removeControl(fieldset); } } }); } , addControl: function(fieldset) { alert("TODO: ADD to fieldset " + fieldset.title); } , removeControl: function(fieldset) { alert("TODO: REMOVE from fieldset" + fieldset.title); } }); ... |
JS – On Ready
Finally; this sections got a lot smaller. Notice that we register the custom controller; without this the UI would still appear, but would not be functional. As mentioned earlier, you could get around having to register a controller by implementing the functionality entirely in the view.
... Ext.onReady(function(){ // Add support for fieldset icons implementFieldsetIcon(); // Register controller Ext.application({name: 'MyCompany', controllers:['FieldsetDynamicControls']}); // Create 2 fieldsets Ext.create('Ext.container.Container',{ renderTo: Ext.getBody() , defaults: { xtype: 'mc_fieldsetdynamiccontrols' , margin: 10 } , items: [ { title: 'Search Filter 1' } , { title: 'Search Filter 2' } ] }); }); // eo onReady ... |
Next -> Complete MVC Controller
Fieldset /w Dynamic Controls (7),
One thought on “Fieldset /w Dynamic Controls (7)”