extjs-gpl
Version:
GPL licensed version of Sencha Ext JS
403 lines (366 loc) • 11.1 kB
JavaScript
/**
* A view controller is a controller that can be attached to a specific view
* instance so it can manage the view and its child components. Each instance of the view
* will have a new view controller, so the instances are isolated.
*
* When a controller is specified on a view, the view automatically becomes a {@link Ext.container.Container#referenceHolder},
* so it will receive inline events declared on the view. Sample usage:
*
* @example
* Ext.define('User', {
* extend: 'Ext.data.Model',
* fields: ['name', 'phone']
* });
*
* Ext.define('UserListController', {
* extend : 'Ext.app.ViewController',
* alias: 'controller.userlist',
*
* init: function(view) {
* this.userCount = 0;
* var users = [],
* i;
*
* for (i = 0; i < 5; ++i) {
* users.push(this.getUser());
* }
* view.getStore().add(users);
* },
*
* onAddClick: function() {
* this.addUser();
* },
*
* onDeleteClick: function() {
* var view = this.getView(),
* selected = view.getSelectionModel().getSelection()[0],
* store = view.getStore();
*
* store.remove(selected);
* },
*
* onSelectionChange: function(selModel, selections) {
* this.lookupReference('delete').setDisabled(selections.length === 0);
* },
*
* getUser: function() {
* ++this.userCount;
* return {
* name: 'User ' + this.userCount,
* phone: this.generatePhone()
* };
* },
*
* addUser: function() {
* this.getView().getStore().add(this.getUser());
* },
*
* generatePhone: function() {
* var num = '',
* i;
*
* for (i = 0; i < 7; ++i) {
* num += Ext.Number.randomInt(0, 9);
* if (num.length === 3) {
* num += '-';
* }
* }
* return num;
* }
* });
*
* Ext.define('UserList', {
* extend: 'Ext.grid.Panel',
* controller: 'userlist',
*
* tbar: [{
* text: 'Add',
* listeners: {
* click: 'onAddClick'
* }
* }, {
* text: 'Delete',
* reference: 'delete',
* listeners: {
* click: 'onDeleteClick'
* }
* }],
* store: {
* model: 'User'
* },
* selModel: {
* type: 'rowmodel',
* listeners: {
* selectionchange: 'onSelectionChange'
* }
* },
* columns: [{
* flex: 1,
* dataIndex: 'name',
* text: 'Name'
* }, {
* flex: 1,
* dataIndex: 'phone',
* text: 'Phone'
* }]
* });
*
* Ext.onReady(function() {
* new UserList({
* renderTo: Ext.getBody(),
* width: 400,
* height: 200
* });
* });
*/
Ext.define('Ext.app.ViewController', {
extend: 'Ext.app.BaseController',
alias: 'controller.controller',
requires: [
'Ext.app.domain.View'
],
mixins: [
'Ext.mixin.Factoryable'
],
isViewController: true,
factoryConfig: { // configure Factoryable
type: 'controller'
},
config: {
closeViewAction: 'destroy'
},
view: null,
constructor: function() {
this.compDomain = new Ext.app.domain.View(this);
this.callParent(arguments);
},
/**
* @method
*
* Called before the view initializes. This is called before the view's
* initComponent method has been called.
* @param {Ext.Component} view The view
* @protected
*/
beforeInit: Ext.emptyFn,
/**
* @method
*
* Called when the view initializes. This is called after the view's initComponent
* method has been called.
* @param {Ext.Component} view The view
* @protected
*/
init: Ext.emptyFn,
/**
* @method
*
* Called when the view model instance for an attached view is first created.
* @param {Ext.app.ViewModel} viewModel The ViewModel
* @protected
*/
initViewModel: Ext.emptyFn,
/**
* Destroy the view controller.
*/
destroy: function() {
var me = this,
domain = me.compDomain;
if (domain) {
domain.unlisten(me);
domain.destroy();
}
me.compDomain = me.view = null;
me.callParent();
},
/**
* This method closes the associated view. The manner in which this is done (that is,
* the method called to close the view) is specified by `closeViewAction`.
*
* It is common for views to map one or more events to this method to allow the view
* to be closed.
*/
closeView: function () {
var view = this.getView(),
action;
if (view) {
action = this.getCloseViewAction();
view[action]();
}
},
control: function(selectors, listeners) {
var obj = selectors;
if (Ext.isString(selectors)) {
obj = {};
obj[selectors] = listeners;
}
this.compDomain.listen(obj, this);
},
listen: function(to, controller) {
var component = to.component;
if (component) {
to = Ext.apply({}, to);
delete to.component;
this.control(component);
}
this.callParent([to, controller]);
},
applyId: function(id) {
if (!id) {
id = Ext.id(null, 'controller-');
}
return id;
},
/**
* @inheritdoc Ext.container.Container#getReferences
* @since 5.0.0
*/
getReferences: function () {
var view = this.view;
return view && view.getReferences();
},
/**
* Get the view for this controller.
* @return {Ext.Component} The view.
*/
getView: function() {
return this.view;
},
/**
* Gets a reference to the component with the specified {@link Ext.Component#reference}
* value.
*
* The method is a short-hand for the {@link #lookupReference} method.
*
* @param {String} key The name of the reference to lookup.
* @return {Ext.Component} The component, `null` if the reference doesn't exist.
* @since 6.0.1
*/
lookup: function (key) {
var view = this.view;
return view && view.lookup(key);
},
/**
* Gets a reference to the component with the specified {@link Ext.Component#reference}
* value.
*
* The {@link #lookup} method is a short-hand version of this method.
*
* @param {String} key The name of the reference to lookup.
* @return {Ext.Component} The component, `null` if the reference doesn't exist.
* @since 5.0.0
*/
lookupReference: function (key) {
return this.lookup(key);
},
/**
* Get a {@link Ext.data.Session} attached to the view for this controller.
* See {@link Ext.Component#lookupSession}.
*
* @return {Ext.data.Session} The session. `null` if no session is found.
*
* @since 5.0.0
*/
getSession: function () {
var view = this.view;
return view && view.lookupSession();
},
/**
* Get a {@link Ext.app.ViewModel} attached to the view for this controller.
* See {@link Ext.Component#lookupViewModel}.
*
* @return {Ext.app.ViewModel} The ViewModel. `null` if no ViewModel is found.
*
* @since 5.0.0
*/
getViewModel: function () {
var view = this.view;
return view && view.lookupViewModel();
},
/**
* Get a {@link Ext.data.Store} attached to the {@link #getViewModel ViewModel} attached to
* this controller. See {@link Ext.app.ViewModel#getStore}.
* @param {String} name The name of the store.
* @return {Ext.data.Store} The store. `null` if no store is found, or there is no
* {@link Ext.app.ViewModel} attached to the view for this controller.
*
* @since 5.0.0
*/
getStore: function(name) {
var viewModel = this.getViewModel();
return viewModel ? viewModel.getStore(name) : null;
},
/**
* Fires an event on the view. See {@link Ext.Component#fireEvent}.
* @param {String} eventName The name of the event to fire.
* @param {Object...} args Variable number of parameters are passed to handlers.
* @return {Boolean} returns false if any of the handlers return false otherwise it returns true.
* @protected
*/
fireViewEvent: function(eventName, firstArg) {
var view = this.view,
result = false,
args = arguments;
if (view) {
if (view !== firstArg) {
args = Ext.Array.slice(args);
args.splice(1, 0, view);
}
result = view.fireEvent.apply(view, args);
}
return result;
},
//=========================================================================
privates: {
view: null,
/**
* Set a reference to a component.
* @param {Ext.Component} component The component to reference
* @private
*/
attachReference: function (component) {
var view = this.view;
if (view) {
view.attachReference(component);
}
},
/**
* Clear a reference to a component
* @param {Ext.Component} ref The component to reference
*
* @private
*/
clearReference: function(ref) {
var view = this.view;
if (view) {
view.clearReference(ref);
}
},
/**
* Invalidates the references collection. Typically called when
* removing a container from this container, since it's difficult
* to know what references got removed.
*
* @private
*/
clearReferences: function () {
var view = this.view;
if (view) {
view.clearReferences();
}
},
/**
* Sets the view for this controller. To be called by the view
* when it initializes.
* @param {Object} view The view.
*
* @private
*/
setView: function(view) {
this.view = view;
if (!this.beforeInit.$nullFn) {
this.beforeInit(view);
}
}
}
});