PDA

View Full Version : Ext objects for model-view-control paradign



mxu
25 Oct 2007, 9:16 PM
hi,

Ext is quite object-oriented, I need a quick catch-up for Ext for fast-paced projects, while at picking up Ext stuffs from docs, I would like to have a better understanding of Ext stuffs
at OOD&A level, but I am unable to find a ref that talks Ext at OOA&D. Could someone point me to such refs if any.

a classical pattern for UI app is M-V-C (model-view-control), what ext objects are , in general, good candidates for model, view and control respectively for client site's 'micro'
M-V-C (excluding server site(s), all web server practically fall into this pattern) ?

thanks

ming

Collin Miller
26 Oct 2007, 1:31 AM
In general anything extending Container will be a view, the Ext.data objects are a bit like models.

Controllers are tricky because both Models and Views fire events. Not sure what the best separation would be....

...but I've been doing some experimentation with something like this:



new Ext.ux.MVC({
name: "App",
config: {
site: "http://localhost:3000"
},

models: {
columnModel: [ Ext.grid.ColumnModel, [
{header: "Name", width: 200, dataIndex: 'name'},
{header: "Number", width: 200, dataIndex: 'number'}
]],

thingStore: [ Ext.data.Store, {}]
},

views: {
north: [ Ext.Panel, {
title: "ARIBITRARY NORTTH!",
split: true,
height: 130,
region: 'north'
}],

rockOff: [ Ext.Panel, {
region: 'center',
title: "ROCK OFF",
id: "rock-off",
layout: 'fit'
}],

grid: [ Ext.grid.GridPanel, function() { return {
cm: this.models.columnModel,
ds: this.models.thingStore,
id: "my-grid",
region: 'north'
}}]
},

controllers: {
viewport: {
'beforerender': function(viewport) {
viewport.add(App.views.rockOff);
viewport.add(App.views.north);
}
},

rockOff: {
'render': function(rockOff) {
rockOff.add(App.views.grid);
}
},
//
// rockOn: {
// 'render': function(rockOn) {
// rockOn.add(App.views.grid);
// }
// },
//
grid: {
'click': function(grid, index, e) {
alert("HEY YOU CLICKED THE GRID!");
}
}
//
// Thing: {
// 'afterfind': function(thing) {
// App.models.thingStore.add(thing);
// }
// }
}
});


And the code for Ext.ux.MVC:


/**
* @class Ext.ux.MVC
* Experimental Model View Controller class
* @cfg {Object} name The MVC application name
* @cfg {Object} config MVC application configs. Such as base URL.
* @cfg {Object} models The models for the app
* @cfg {Object} views The views for the app
* @cfg {Object} controllers The event handlers for the app
* @constructor
* Create a new Ext MVC app
* @param {Object} config The config object
*/


Ext.ux.MVC = function(config) {
if (!config.name) {throw "Provide a name for your MVC app.";}
this.generateSkeleton(config.name);
this.populateSkeleton(config);
this.buildModels();
Ext.onReady(this.bootViewport.createDelegate(this));

}

Ext.ux.MVC.prototype = {
//private
CONSTRUCTOR: 0,

//private
CONFIG: 1,

/**
* Generates an enmpty application skeleton. Uses Ext.namespace and sets window[name] to
* the generated namespace.
* @param {name} name The name to use when creating the application namespace
*/
generateSkeleton: function(name) {
Ext.namespace(name);
window[name] = this;
Ext.apply(this, {
models: {},
views: {},
controllers: {},
config: {}
});
},

//private
// fill in the app skeleton with user provided config
populateSkeleton: function(config) {
Ext.apply(this.models, config.models);
Ext.apply(this.views, config.views);
Ext.apply(this.controllers, config.controllers);
Ext.apply(this.config, config.config);

/* Highly experimental and RoR specific */
// Ext.apply(skeleton.config, {
// resource: {
// site: skeleton.config.site,
// scope: skeleton.app.models,
// transport: Ext.ux.Rest.transport
// }
// });
},

//private
// Iterates over all models.
// If config for a model is a function the result of the function will be used
// as the arguments for the constructor.
buildModels: function(app, resourceConfig) {
var slot, models = this.models, constructor, config;

/* Highly experimental and RoR specific */
// Ext.each(models.resources||[],
// function(resource) {
// Resource(resource, resourceConfig);
// });

for (slot in models) {
constructor = models[slot][this.CONSTRUCTOR];
config = models[slot][this.CONFIG];
if (typeof constructor == "function") {
if (typeof config == "function") {
models[slot] = new constructor(config.call(app));
}
else {
models[slot] = new constructor(config);
}
}
}
},

//private
bootViewport: function() {
new Ext.Viewport({
layout: 'border',
plugins: {
init: this.onViewportBoot.createDelegate(this)
}
});
},

//private
onViewportBoot: function(viewport) {
this.views.viewport = viewport;
this.instantiateViews();
this.applyControllers();
},

//private
// Iterates over all views.
// If config for a views is a function the result of the function will be used
// as the arguments for the constructor.
instantiateViews: function() {
var slot, views = this.views, constructor, config;

for (slot in views) {
constructor = views[slot][this.CONSTRUCTOR];
config = views[slot][this.CONFIG];
if (typeof constructor == "function") {
if (typeof config == "function") {
views[slot] = new constructor(config.call(this));
}
else {
views[slot] = new constructor(config);
}
}
}
},

//private
// Looks up named components in the views or models namespaces of the app.
// Uses Obsevable#on to apply function to event.
applyControllers: function() {
var slot, component, componentToUse, event, eventName,
controllers = this.controllers,
models = this.models
views = this.views;

for (slot in controllers) {
component = models[slot] || views[slot] || null;
if (!component) { throw "Attempted to attach events to non-existant component: "+slot }
else {
for (event in controllers[slot]) {

splitEvent = event.split(":");
if (splitEvent.length == 1) {
component.on(splitEvent[0], controllers[slot][event]);
}
else {
eventName = splitEvent.pop();
componentToUse = component;
Ext.each(splitEvent[0].split("."),
function(property){
componentToUse = componentToUse[property];
})
componentToUse.on(eventName, controllers[slot][event])
}
}
}
}
}
};

I'm working on a botter demo soon, involving more of my extentions, but this is one of the bits I've really started documenting and getting ready.