Our competences at your disposal on our blog
We love our job and we are glad to share it with you! Keep yourself fully informed about news and technologies we use to develop and which you may need! Follow our blog.
×

Error message

The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.
mattia.minotti's picture

Since April 2011, Sencha has introduced the MVC (Model-View-Controller) design pattern into the core of its products, with the release of ExtJs version 4.0.
Only recently it has reached a certain maturity thanks to bugfixes and improvements, which led to the release of the 4.2.1 version, and thanks to the integration of the official documentation, inclusive of articles and examples.

To not dwell too much on the details by which this pattern has been applied by Sencha (for those wishing to deepen highly recommend to consult the official guide), below we want to give some tips that might facilitate the transition from the classical style of client-side web application programming to this new approach.

Controllers Design

One of the first aspects, not trivial at all, of the MVC pattern implementation proposed by Sencha is that controllers are singleton class. Invoking, from a controller, the method for the creation of another controller, allows the framework to proceed with its creation and with the invocation of the init method, only if it doesn’t already exist.

this.getController("ExampleController");

The controller univocal id is the parameter required by this method, indeed, and it corresponds to the class name which implements it (and to the file that includes it). It is not possible to allocate two controller of the same type with two different ids.
Being a singleton, every controller must act in an active or reactive way on all the instances of the View for which it has been designed (remember that for every View may exist innumerable instances).
A classic example is that of a Controller C which has to run a set of Views V1, V2 and Vn... The reactive phase is run through the method control offered by every controller.
It allows you to register callbacks to certain events of all Views of a particular type or within a certain path, but generally is not used to identify a specific View instance. This means that within the callback, triggered by an internal View component, you do not have a direct reference to it even if it has to be recovered in some way, in order to identify which of the n instances it is.
One possible approach (however is not the one suggested) is to save in the controller level the references to all the View that it manages, and then use them to perform operations within the callback. But the problem is: how can we recognize the View who ran the event in between the instances observed by the Controller? It’s clear that by doing this, the management is far more complicated.
Personally, we have adopted a more linear solution which achieved particular success, and so we would like to promote it: the total reliability on the ExtJs ComponentQuery mechanism. Let’s try to explain it with an example:

Ext.define('MyApp.view.V', {
     extend: 'Ext.container.Container',
     alias: 'widget.v',
     initComponent: function() {
    	this.items = [
    	    	{
    		    	xtype: 'button',
		    	text: 'do',
    		    	action: 'do'
    		},{
			xtype: 'textfield',
			name: 'value'
    	    	}
    	];
    	this.callParent();
     }
});

Ext.define('MyApp.controller.C, {
     extend: 'Ext.app.Controller',

     init: function() {
	this.control({
     		'v button[action=do]': {
    	    	    	click: function(button){
    	    	    		var v = button.up('v');
    	    	    		var value = v.down('textfield[name=value]');
    	    	    		value.setValue('Hello World');
    	    	    	}
    	    	}
    	});
     }
});

Suppose you instantiate a Controller C-type and nV-type Views. Now you need to understand how the button click event is handled and how it changes the text of the field that is in the same View of the button (and not in the others). Basically the method avoids to use a reference to the Views stored beforehand into the Controller but extracts it using the ComponentQuery method and starting from the component that has generated the event.
In the example, starting from the button that generates the event, it is possible to obtain the reference to the View that contains it, implementing a traversing upwards:

var v = button.up('v');

From this it is necessary to go down in order to find the textfield, starting from the View reference achieved earlier:

var value = v.down('textfield[name=value]');

Modeling the Controller after this method, without connecting it directly to the View which it manages, it results easier and more generic.
Essentially, following this pattern, it is possible to implement a Controller, designing it for a single View. In case the View has been allocated repeatedly, the support turns out to be basically free.

Windows and Component Query

Following this method and, above all, Sencha’s guideline, the use of the Query Components becomes essential. Even if the query are powerful and very convenient, they have a limit: they operate researches on component threads which are bound to their hierarchical DOM structure.
A typical problem is that of the reference recovery to a Window which has been created from a specific application View (for example a modal). In ExtJS, by default, windows are inserted into the DOM, directly within the element body, therefore if you use the Component Query there is no way to reach the View to which are connected, starting from their reference and vice versa.
In order to solve this problem, as long as Sencha won’t supply more structured mechanism, a possible solution is that of defining, within the window, a direct reference to the parent, that is the View to which it must be linked. Doing so, starting from a window reference, obtained by the standard Component Query mechanism, you will gain a reference to the parent View and then to all its child components on which you can operate as needed.
The following example shows how a View V includes a button that, if pushed, it will open a Window W linked to the View through tha parent field. Such Window has a button that once is pushed, it is able to recover the reference to the View linked through the parent field and operates on it:

Ext.define('MyApp.view.V', {
     extend: 'Ext.container.Container',
     alias: 'widget.v',
     initComponent: function() {
    	this.items = [
    	    {
    	    	xtype: 'button',
    	    	text: 'do',
    	    	action: 'do'
    		},{
    			xtype: 'textfield',
    			name: 'value'
    		}
    	];
    	this.callParent();
     }
});

Ext.define('MyApp.view.W', {
     extend: 'Ext.window.Window',
     alias: 'widget.w',
     initComponent: function() {
    	 this.items = [
    	    {
    	    	xtype: 'button',
    	    	text: 'do',
    	    	action: 'do'
    		}
    	 ];
    	 this.callParent();
     }
});

Ext.define('MyApp.controller.C', {
     extend: 'Ext.app.Controller',

     init: function() {
    	 this.control({
    		 'v button[action=do]': {
    			 click: function(button){
    				 var v = button.up('v');
    				 var w = Ext.create('w');
    				 w.parent = v;
    				 w.show();
    			 }
    		 },
    		 'w button[action=do]': {
    			 click: function(button){
    				 var w = button.up('w');

    				 //this is the jump from the window and its view
    				 var v = w.parent;

    				 var value = v.down('textfield[name=value]');
    				 value.setValue('Hello World');
    				 w.hide();
    			 }
    		 }
    	 });
     }
});

This method, once again, turns out to be really useful in case the application provides more instance of the same View, not recognizable from their id.

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.