4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-app-Controller'>/**
19 </span> * @class Ext.app.Controller
21 * Controllers are the glue that binds an application together. All they really do is listen for events (usually from
22 * views) and take some action. Here's how we might create a Controller to manage Users:
24 * Ext.define('MyApp.controller.Users', {
25 * extend: 'Ext.app.Controller',
28 * console.log('Initialized Users! This happens before the Application launch function is called');
32 * The init function is a special method that is called when your application boots. It is called before the
33 * {@link Ext.app.Application Application}'s launch function is executed so gives a hook point to run any code before
34 * your Viewport is created.
36 * The init function is a great place to set up how your controller interacts with the view, and is usually used in
37 * conjunction with another Controller function - {@link Ext.app.Controller#control control}. The control function
38 * makes it easy to listen to events on your view classes and take some action with a handler function. Let's update
39 * our Users controller to tell us when the panel is rendered:
41 * Ext.define('MyApp.controller.Users', {
42 * extend: 'Ext.app.Controller',
46 * 'viewport > panel': {
47 * render: this.onPanelRendered
52 * onPanelRendered: function() {
53 * console.log('The panel was rendered');
57 * We've updated the init function to use this.control to set up listeners on views in our application. The control
58 * function uses the new ComponentQuery engine to quickly and easily get references to components on the page. If you
59 * are not familiar with ComponentQuery yet, be sure to check out the {@link Ext.ComponentQuery documentation}. In brief though,
60 * it allows us to pass a CSS-like selector that will find every matching component on the page.
62 * In our init function above we supplied 'viewport > panel', which translates to "find me every Panel that is a direct
63 * child of a Viewport". We then supplied an object that maps event names (just 'render' in this case) to handler
64 * functions. The overall effect is that whenever any component that matches our selector fires a 'render' event, our
65 * onPanelRendered function is called.
67 * <u>Using refs</u>
69 * One of the most useful parts of Controllers is the new ref system. These use the new {@link Ext.ComponentQuery} to
70 * make it really easy to get references to Views on your page. Let's look at an example of this now:
72 * Ext.define('MyApp.controller.Users', {
73 * extend: 'Ext.app.Controller',
85 * click: this.refreshGrid
90 * refreshGrid: function() {
91 * this.getList().store.load();
95 * This example assumes the existence of a {@link Ext.grid.Panel Grid} on the page, which contains a single button to
96 * refresh the Grid when clicked. In our refs array, we set up a reference to the grid. There are two parts to this -
97 * the 'selector', which is a {@link Ext.ComponentQuery ComponentQuery} selector which finds any grid on the page and
98 * assigns it to the reference 'list'.
100 * By giving the reference a name, we get a number of things for free. The first is the getList function that we use in
101 * the refreshGrid method above. This is generated automatically by the Controller based on the name of our ref, which
102 * was capitalized and prepended with get to go from 'list' to 'getList'.
104 * The way this works is that the first time getList is called by your code, the ComponentQuery selector is run and the
105 * first component that matches the selector ('grid' in this case) will be returned. All future calls to getList will
106 * use a cached reference to that grid. Usually it is advised to use a specific ComponentQuery selector that will only
107 * match a single View in your application (in the case above our selector will match any grid on the page).
109 * Bringing it all together, our init function is called when the application boots, at which time we call this.control
110 * to listen to any click on a {@link Ext.button.Button button} and call our refreshGrid function (again, this will
111 * match any button on the page so we advise a more specific selector than just 'button', but have left it this way for
112 * simplicity). When the button is clicked we use out getList function to refresh the grid.
114 * You can create any number of refs and control any number of components this way, simply adding more functions to
115 * your Controller as you go. For an example of real-world usage of Controllers see the Feed Viewer example in the
116 * examples/app/feed-viewer folder in the SDK download.
118 * <u>Generated getter methods</u>
120 * Refs aren't the only thing that generate convenient getter methods. Controllers often have to deal with Models and
121 * Stores so the framework offers a couple of easy ways to get access to those too. Let's look at another example:
123 * Ext.define('MyApp.controller.Users', {
124 * extend: 'Ext.app.Controller',
127 * stores: ['AllUsers', 'AdminUsers'],
130 * var User = this.getUserModel(),
131 * allUsers = this.getAllUsersStore();
133 * var ed = new User({name: 'Ed'});
138 * By specifying Models and Stores that the Controller cares about, it again dynamically loads them from the appropriate
139 * locations (app/model/User.js, app/store/AllUsers.js and app/store/AdminUsers.js in this case) and creates getter
140 * functions for them all. The example above will create a new User model instance and add it to the AllUsers Store.
141 * Of course, you could do anything in this function but in this case we just did something simple to demonstrate the
144 * <u>Further Reading</u>
146 * For more information about writing Ext JS 4 applications, please see the
147 * [application architecture guide](#/guide/application_architecture). Also see the {@link Ext.app.Application} documentation.
149 * @docauthor Ed Spencer
151 Ext.define('Ext.app.Controller', {
154 observable: 'Ext.util.Observable'
157 <span id='Ext-app-Controller-cfg-id'> /**
158 </span> * @cfg {String} id The id of this controller. You can use this id when dispatching.
161 <span id='Ext-app-Controller-cfg-models'> /**
162 </span> * @cfg {String[]} models
163 * Array of models to require from AppName.model namespace. For example:
165 * Ext.define("MyApp.controller.Foo", {
166 * extend: "Ext.app.Controller",
167 * models: ['User', 'Vehicle']
170 * This is equivalent of:
172 * Ext.define("MyApp.controller.Foo", {
173 * extend: "Ext.app.Controller",
174 * requires: ['MyApp.model.User', 'MyApp.model.Vehicle']
179 <span id='Ext-app-Controller-cfg-views'> /**
180 </span> * @cfg {String[]} views
181 * Array of views to require from AppName.view namespace. For example:
183 * Ext.define("MyApp.controller.Foo", {
184 * extend: "Ext.app.Controller",
185 * views: ['List', 'Detail']
188 * This is equivalent of:
190 * Ext.define("MyApp.controller.Foo", {
191 * extend: "Ext.app.Controller",
192 * requires: ['MyApp.view.List', 'MyApp.view.Detail']
197 <span id='Ext-app-Controller-cfg-stores'> /**
198 </span> * @cfg {String[]} stores
199 * Array of stores to require from AppName.store namespace. For example:
201 * Ext.define("MyApp.controller.Foo", {
202 * extend: "Ext.app.Controller",
203 * stores: ['Users', 'Vehicles']
206 * This is equivalent of:
208 * Ext.define("MyApp.controller.Foo", {
209 * extend: "Ext.app.Controller",
210 * requires: ['MyApp.store.Users', 'MyApp.store.Vehicles']
215 onClassExtended: function(cls, data) {
216 var className = Ext.getClassName(cls),
217 match = className.match(/^(.*)\.controller\./);
219 if (match !== null) {
220 var namespace = Ext.Loader.getPrefix(className) || match[1],
221 onBeforeClassCreated = data.onBeforeClassCreated,
223 modules = ['model', 'view', 'store'],
226 data.onBeforeClassCreated = function(cls, data) {
228 items, j, subLn, item;
230 for (i = 0,ln = modules.length; i < ln; i++) {
233 items = Ext.Array.from(data[module + 's']);
235 for (j = 0,subLn = items.length; j < subLn; j++) {
238 prefix = Ext.Loader.getPrefix(item);
240 if (prefix === '' || prefix === item) {
241 requires.push(namespace + '.' + module + '.' + item);
249 Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
254 <span id='Ext-app-Controller-method-constructor'> /**
255 </span> * Creates new Controller.
256 * @param {Object} config (optional) Config object.
258 constructor: function(config) {
259 this.mixins.observable.constructor.call(this, config);
261 Ext.apply(this, config || {});
263 this.createGetters('model', this.models);
264 this.createGetters('store', this.stores);
265 this.createGetters('view', this.views);
272 <span id='Ext-app-Controller-method-init'> /**
273 </span> * A template method that is called when your application boots. It is called before the
274 * {@link Ext.app.Application Application}'s launch function is executed so gives a hook point to run any code before
275 * your Viewport is created.
277 * @param {Ext.app.Application} application
280 init: function(application) {},
282 <span id='Ext-app-Controller-method-onLaunch'> /**
283 </span> * A template method like {@link #init}, but called after the viewport is created.
284 * This is called after the {@link Ext.app.Application#launch launch} method of Application is executed.
286 * @param {Ext.app.Application} application
289 onLaunch: function(application) {},
291 createGetters: function(type, refs) {
292 type = Ext.String.capitalize(type);
293 Ext.Array.each(refs, function(ref) {
295 parts = ref.split('.');
297 // Handle namespaced class names. E.g. feed.Add becomes getFeedAddView etc.
298 Ext.Array.each(parts, function(part) {
299 fn += Ext.String.capitalize(part);
304 this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
306 // Execute it right away
312 ref: function(refs) {
314 refs = Ext.Array.from(refs);
315 Ext.Array.each(refs, function(info) {
317 fn = 'get' + Ext.String.capitalize(ref);
319 me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
324 getRef: function(ref, info, config) {
325 this.refCache = this.refCache || {};
327 config = config || {};
329 Ext.apply(info, config);
331 if (info.forceCreate) {
332 return Ext.ComponentManager.create(info, 'component');
336 selector = info.selector,
337 cached = me.refCache[ref];
340 me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
341 if (!cached && info.autoCreate) {
342 me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
345 cached.on('beforedestroy', function() {
346 me.refCache[ref] = null;
354 <span id='Ext-app-Controller-method-control'> /**
355 </span> * Adds listeners to components selected via {@link Ext.ComponentQuery}. Accepts an
356 * object containing component paths mapped to a hash of listener functions.
358 * In the following example the `updateUser` function is mapped to to the `click`
359 * event on a button component, which is a child of the `useredit` component.
361 * Ext.define('AM.controller.Users', {
364 * 'useredit button[action=save]': {
365 * click: this.updateUser
370 * updateUser: function(button) {
371 * console.log('clicked the Save button');
375 * See {@link Ext.ComponentQuery} for more information on component selectors.
377 * @param {String/Object} selectors If a String, the second argument is used as the
378 * listeners, otherwise an object of selectors -> listeners is assumed
379 * @param {Object} listeners
381 control: function(selectors, listeners) {
382 this.application.control(selectors, listeners, this);
385 <span id='Ext-app-Controller-method-getController'> /**
386 </span> * Returns instance of a {@link Ext.app.Controller controller} with the given name.
387 * When controller doesn't exist yet, it's created.
388 * @param {String} name
389 * @return {Ext.app.Controller} a controller instance.
391 getController: function(name) {
392 return this.application.getController(name);
395 <span id='Ext-app-Controller-method-getStore'> /**
396 </span> * Returns instance of a {@link Ext.data.Store Store} with the given name.
397 * When store doesn't exist yet, it's created.
398 * @param {String} name
399 * @return {Ext.data.Store} a store instance.
401 getStore: function(name) {
402 return this.application.getStore(name);
405 <span id='Ext-app-Controller-method-getModel'> /**
406 </span> * Returns a {@link Ext.data.Model Model} class with the given name.
407 * A shorthand for using {@link Ext.ModelManager#getModel}.
408 * @param {String} name
409 * @return {Ext.data.Model} a model class.
411 getModel: function(model) {
412 return this.application.getModel(model);
415 <span id='Ext-app-Controller-method-getView'> /**
416 </span> * Returns a View class with the given name. To create an instance of the view,
417 * you can use it like it's used by Application to create the Viewport:
419 * this.getView('Viewport').create();
421 * @param {String} name
422 * @return {Ext.Base} a view class.
424 getView: function(view) {
425 return this.application.getView(view);