Posts Tagged coding practices

Primitive OOP observer pattern with ExtJS

Recently I embarked on a quest to design a framework which would help us keep track of large and complex javascript projects in easily identifiable and extendable patterns. After some thought and deliberation, we eventually settled on the observer pattern using Ext’s Ext.util.Observable object as the base object to use in responding to event broadcasts and the Ext.ux.BroadcastEvents plugin for managing global event broadcasts.

Here is the code I came up with for common component elements:

ComponentWrapperBase = Ext.extend(Ext.util.Observable, {
	delayBuild: false,
	
	eventObj: {
			"buildwidget": true,
			"showwidget": true,
			"destroy": true,
			"refresh": true
		},
		
	globalEvents: [],
	
	widget: null,
	widgetCfg: null,
	
	build: function() {
		if (this.widgetCfg && !this.widget) {
			//console.log("buildwidget", this);
			this.widget = Ext.ComponentMgr.create(this.widgetCfg);
			this.widget.wrapper = this;
			this.fireBuildEvent();
		}
	},
	
	fireBuildEvent: function() {
		this.fireEvent("buildwidget", this, this.widget);
	},
	
	showWidget: function(locationId) {
		if (this.widget) {
			if (this.widget.xtype == "window") {
					if (locationId != null) {
						this.widget.show(locationId);
					} else {
						this.widget.show();
					}
			}
			else {
			
				if (locationId != null) {
					this.widget.render(locationId);
				}
				else {
					this.widget.render();
				}
			}
			this.fireEvent("showwidget", this);
		}
	},
	
	constructor: function(config){
		if (config) {
			if (config.widgetCfg) {
				this.widgetCfg = config.widgetCfg;
			}
			
			if (config.delayBuild) {
				this.delayBuild = config.delayBuild;
			}
			
			// Copy configured listeners into *this* object so that the base class's
			// constructor will add them.
			if (config.listeners) {
				Ext.apply(this.listeners,config.listeners);
			}
			
			if(config.events && Ext.isArray(config.events)) {
				for (var i=0; i

This creates a simple widget wrapped in an Observable object. You can reach the contained widget through wrapper.widget. Using the framework above, here's how you could create a simple widget.

SimpleTextField = Ext.extend(ComponentWrapperBase, {
	widgetCfg: {
		xtype: 'textfield',
		fieldLabel: 'Name'
	},
	constructor: function(config){		// Constructor is not required, but I've included 
							// it to demonstrate the flexibility of this framework
		if (config) {
			Ext.apply(this,config);
		}
		
		this.widgetCfg.value = 'John Smith';
		
		SimpleTextField.superclass.constructor.call(this);
	}
});

var simpleTextField = new SimpleTextField();
// Actual component is available at simpleTextField.widget, useful for adding to other containers

That's it! If you have any questions or comments, feel free to post them below.

Share/Save

Tags: , , , , ,

Warning: JSLint will hurt your feelings

JSLint is a very helpful code quality utility for javascript that purports to hurt your feelings but helps you write ECMAScript compliant code. Many development suites like Aptana now include lint checking while you code.

A major advantage of making sure your code is linted is that it ensures your code will not be mangled too badly by minification/obfuscators if you decide to use them later on.

Tags: , , , , , , ,