ExtJs4 (11) MVC application mode and extjs4mvc Application Mode
For Extjs, large client programs have been hard to write. When you add more functions and projects to large client programs, the project volume increases rapidly. Such a large client program is difficult to organize and maintain. Therefore, Extjs4 is equipped with a new application architecture that can structure your code, that is, Extjs4 MVC.
Extjs4 MVC is different from other MVC architectures. Extjs has its own definition:
In this article, we will create a very simple application, that is, user data management. Finally, you will know how to use Extjs4 MVC to create a simple application. The Extjs4 MVC application architecture provides the structure and consistency of the application. This model has brought about some important benefits:
Since we are introducing Extjs4 MVC, let's start to create this application. File Structure: Extjs4 MVC applications follow a unified directory Structure like other applications. In the MVC layout, all classes are placed in the application folder. Its subfolders include your namespace, model, view, Controller, and memory. The following is a simple example to illustrate how to apply it.
In this example, we place the entire application in a folder named "account_manager". The structure in the "account_manager" folder is shown in. Edit index.html as follows:
Create an app. js file (Creating the application) All Extjs4 MVC applications are still Ext. an instance of the application starts. The application should include global settings, models, views, and controllers used by the application ), an application should also include a launch function ).
Create a simple account management application. First, select a namespace (all extjs4 applications should use a single global change as the namespace ). Currently, "AM" is used as the namespace.
Ext.application({name : 'AM',appFolder : 'app',launch : function() {Ext.create('Ext.container.Viewport', {layout : 'fit',items : [ {xtype : 'panel',title : 'Users',html : 'List of users will go here'} ]});}});
The above Code does the following. First, call Ext. the application creates an application class instance and sets an "AM" namespace. It will be used as the global variable of the entire application and Ext. loader namespace, and then use appFolder to specify the corresponding path for configuration selection. Finally, a simple launch function is created. Here, only a Viewport is created, with a ton of panel in the package to fill the entire window.
Defining a Controller is the key to the entire application. It is responsible for listening to events and performing corresponding actions on some time points. Now we create a controller named Users. js. The path is app/controller/Users. js. Then, we add the following code for Users. js:
Ext.define('AM.controller.Users', {extend: 'Ext.app.Controller',init: function() {console.log('Initialized Users! This happens before the Application launch function is called');}});
After that, add the created controller to the application configuration file: app. js:
Ext.application({...controllers: ['Users'],...});
When we upload index.html, the user controller (Users. js) is automatically loaded, because we specify the parameters in the preceding app. js. The best thing about the Init counts is the interaction between the Controller and the view. The interaction here refers to the control function, because it can easily listen to the number of views for event processing, take appropriate measures and render relevant information to the Panel in a timely manner. Write Users. js:
Ext.define('AM.controller.Users', {extend : 'Ext.app.Controller',init : function() {this.control({'viewport > panel' : {render : this.onPanelRendered}});},onPanelRendered : function() {console.log('The panel was rendered');}});
In Users. in js, The init Worker Number uses this. the new ComponentQuery engine is used for monitoring, so you can quickly and conveniently find the reference (viewport> panel) of components on the page. This is similar to the CSS selector, quickly find matching components. In the above init records, we use viewport> panel to find the app. in js, we provide an object processing function (this. onPanelRendered. Note that the object here is this, and its processing function is onPanelRendered ). The overall effect is that the handler must meet any component that triggers the render event, and the onPanelRendered function will be called. When running our application, we will see the following content.
Define a View (Defining a View). Up to now, the application pipeline has several lines and two files, app. js and app/controller/Users. js. Now we add a grid to display all users in the system. As a subclass of the view component, we create a new file, which is stored in the app/view/user directory by the handler. Name it List. js. The entire path is like this. App/view/user/List. js. Below, we will write the code for List. js:
Ext.define('AM.view.user.List', {extend : 'Ext.grid.Panel',alias : 'widget.userlist',title : 'All Users',initComponent : function() {this.store = {fields : [ 'name', 'email' ],data : [ {name : 'Ed',email : 'ed@sencha.com'}, {name : 'Tommy',email : 'tommy@sencha.com'} ]};this.columns = [ {header : 'Name',dataIndex : 'name',flex : 1}, {header : 'Email',dataIndex : 'email',flex : 1} ];this.callParent(arguments);}});
The created class is a very common class and has no significance. To make it easier for us to use the defined class, we use alias to define an alias, in this case, we can use Ext. create () and Ext. create widgets (). You can also use xtype to create widgets in other widgets.
Ext.define('AM.controller.Users', {extend: 'Ext.app.Controller',views: ['user.List'],init: ...onPanelRendered: ...});
Modify Users. js, add the views attribute, modify the launch method in app. js, and render the List to the Viewport.
Ext.application({...launch: function() {Ext.create('Ext.container.Viewport', {layout: 'fit',items: {xtype: 'userlist'}});}});
Some people may get crazy when they see this. How is this user. List written? Why? If you are confused, you may wish to look at Ext. how Loader works (see other sections of this document. after Loader, you will understand, User. list is the List under app/view/user. js file. Why does Ext need to be retrieved from the view? Because we set views: ['user. list'] In the controller. This is the power of Extjs dynamic loading. For more information about Ext. Loader, see other articles on this site. When we refresh the page.
Note that the onPanelRendered function is still called. This is because gird matches 'viewport> panel '. Then we add a listener. When we double-click the row in the grid, We can edit the user.
Ext.define('AM.controller.Users', {extend : 'Ext.app.Controller',views : [ 'user.List' ],init : function() {this.control({'userlist' : {itemdblclick : this.editUser}});},editUser : function(grid, record) {console.log('Double clicked on ' + record.get('name'));}});
Here, we have modified the ComponentQuery selection ('userlist') and event name ('itemdblclick') and processing function ('edituser ').
If you want to edit a user, you need to edit a window for the user and create a JS file. The path is app/view/user/Edit. js. The Code is as follows:
Ext.define('AM.view.user.Edit', {extend : 'Ext.window.Window',alias : 'widget.useredit',title : 'Edit User',layout : 'fit',autoShow : true,initComponent : function() {this.items = [ {xtype : 'form',items : [ {xtype : 'textfield',name : 'name',fieldLabel : 'Name'}, {xtype : 'textfield',name : 'email',fieldLabel : 'Email'} ]} ];this.buttons = [ {text : 'Save',action : 'save'}, {text : 'Cancel',scope : this,handler : this.close} ];this.callParent(arguments);}});
We define a subclass that inherits Ext. window. Window, and then creates a form and two buttons using initComponent. In the form, two fields are loaded with the user name and email respectively. Next, modify the View Controller so that it can load user data.
Ext.define('AM.controller.Users', {extend: 'Ext.app.Controller',views: ['user.List','user.Edit'],init: ...editUser: function(grid, record) {var view = Ext.widget('useredit');view.down('form').loadRecord(record);}});
First, use the convenient Ext. widget method for the created view, which is equivalent to Ext. create ('widget. useredit ―). Then, we use ComponentQuery to quickly obtain the reference in the form of an edited user. Each component in Ext JS4 has a down function that can be used to quickly find any child component. Double-click the row in the Grid, as shown in:
Create Model and Store
Ext.define('AM.store.Users', {extend : 'Ext.data.Store',fields : [ 'name', 'email' ],data : [ {name : 'Ed',email : 'ed@sencha.com'}, {name : 'Tommy',email : 'tommy@sencha.com'} ]});
Next, modify two files:
Ext.define('AM.controller.Users', {extend: 'Ext.app.Controller',stores: ['Users'],...});
Modify app/view/user/List. js to reference Users
Ext.define('AM.view.user.List' ,{extend: 'Ext.grid.Panel',alias : 'widget.userlist',//we no longer define the Users store in the `initComponent` methodstore: 'Users',...});
Now, the user controller we define can load data smoothly. Up to now, the Store we define is enough, but Extjs4 provides a powerful Ext. data. the Model class is better. We can use it to reconstruct our Store and create app/model/User. js
Ext.define('AM.model.User', {extend : 'Ext.data.Model',fields : [ 'name', 'email' ]});
After creating the model, we will introduce it to user control:
//the Users controller will make sure that the User model is included on the page and available to our appExt.define('AM.controller.Users', {extend: 'Ext.app.Controller',stores: ['Users'],models: ['User'],...});// we now reference the Model instead of defining fields inlineExt.define('AM.store.Users', {extend: 'Ext.data.Store',model: 'AM.model.User',data: [ {name: 'Ed', email: 'ed@sencha.com'}, {name: 'Tommy', email: 'tommy@sencha.com'}]});
After completing the above Code, refresh the page and see the same results as before.
Double-click the row in the Grid to Save the data using the model. The edit user window is displayed. To Save the user data, modify the init function.
Ext.define('AM.controller.Users', {init : function() {this.control({'viewport > userlist' : {itemdblclick : this.editUser},'useredit button[action=save]' : {click : this.updateUser}});},updateUser : function(button) {console.log('clicked the Save button');}});
In this. in control, we add a selection item, 'useredit button [action = save] '. When ComponentQuery finds the matching component (button and action is save ), add a method click to the user, and the event is updateUser.
You can see the correct Click event. In the updateUser function, a formal logic is required to update user data.
updateUser:function(button) {var win = button.up('window'),form = win.down('form'),record = form.getRecord(),values = form.getValues();record.set(values);win.close();}
Here, when we click the Save button, we pass the button itself into the updateUser function, then we use the button. up ('window') to obtain the reference of the user window, and then use win. <G id = "1"> </G>.
After modifying the data, click Save. The update is complete.
In actual application, we need to save the data to the server. Therefore, we need to modify the file to achieve the desired purpose. It is easy to save data to the server. Use AJAX.
Ext.define('AM.store.Users', {extend : 'Ext.data.Store',model : 'AM.model.User',autoLoad : true,proxy : {type : 'ajax',url : 'data/users.json',reader : {type : 'json',root : 'users',successProperty : 'success'}}});
In AM. store. Users, remove data, replace it with a proxy, and load and save data as a proxy. In Extjs4, the proxy methods are AJAX, JSON-P and HTML5 localStorage, where AJAX proxy is used. The data is obtained from data/users. json. We also use reader to parse data and specify the successProperty configuration. For details, see Json Reader and copy the previous data to users. json. The format is as follows:
{success:true,users:[ {id: 1, name: 'Ed', email: 'ed@sencha.com'}, {id: 2, name: 'Tommy', email: 'tommy@sencha.com'}]}
The only change here is to set Stroe's autoLoad to true, which requires the Stroe proxy to automatically load data. When refreshing the page, it will get the same effect as before. The last thing is to send the modified data to the server. In this example, the server only uses a static JSON file, so we will not see any changes, but at least we can determine that this is feasible. We believe that the server can process data. In this example, make a small change, that is, in the new proxy, use the api to update a new URL.
proxy: {type: 'ajax',api: {read: 'data/users.json',update: 'data/updateUsers.json'},reader: {type: 'json',root: 'users',successProperty: 'success'}}
Let's take a look at how it runs. We are still reading users. json data, and any update will be sent to updateUsers. json, in updateUsers. create a virtual response in json to let us know that the event has actually occurred. UpdateUsers. json only contains {"success": true }. The only thing we have to do is to synchronously edit the service. This function is added to the updateUser function.
updateUser: function(button) {var win = button.up('window'),form = win.down('form'),record = form.getRecord(),values = form.getValues();record.set(values);win.close();this.getUsersStore().sync();}
Now, run this complete example. When you double-click a grid item and edit it, click Save to get the correct request and response.
So far, the entire MVC mode is complete.