Cleaning up an example Ext JS form
August 8, 2008 7 Comments
One of my recent Ext JS forms had a section which looked like this:
items: [ new Ext.Button({ text: 'Preview Video', iconCls: 'play', handler: function() { var win; if (!win) { win = new Ext.Window({ title: 'Preview Video', modal: true, height: 377, width: 368, items: [ new Ext.Panel({ autoLoad: '/admin/videos/' + video_id + '/preview.html' }) ], buttons: [ { text: 'OK', handler: function() { win.close(); } } ] }); }; win.show(); } }) ]
Not horrific but not nice either – let’s DRY this up. It’s not too pleasant to read but all it’s really doing is rendering a customised Ext.Button which opens up a modal Ext.Window, in which is loaded the contents of a known url.
Ok so let’s start with that Window. First, we’ll make a subclass of Ext.Window:
/** * AdFunded.views.Video.PreviewWindow * @extends Ext.Window * A simple Preview window for the given video_id */ AdFunded.views.Video.PreviewWindow = function(config) { var config = config || {}; Ext.applyIf(config, { title: 'Preview Video', modal: true, height: 377, width: 368, items: [ new Ext.Panel({ autoLoad: '/admin/videos/' + config.video_id + '/preview.html' }) ], buttons: [ { text: 'OK', scope: this, handler: function() { this.window.close(); } } ] }); AdFunded.views.Video.PreviewWindow.superclass.constructor.call(this, config); this.window = this; }; Ext.extend(AdFunded.views.Video.PreviewWindow, Ext.Window); Ext.reg('video_preview_window', AdFunded.views.Video.PreviewWindow);
Note the namespacing employed above – within an Ext MVC framework I have been developing across several projects for the last few months, all views follow this structure. AdFunded is the name of the application. The precise structure doesn’t matter here, but using a namespace for each app does.
So we’ve taken the Window setup out of our view now, which leaves us with:
items: [ new Ext.Button({ text: 'Preview Video', iconCls: 'play', handler: function() { var win; if (!win) { win = new AdFunded.views.Video.PreviewWindow({video_id: id}); }; win.show(); } }) ]
Great – we’ve gone from 34 lines in our view to 15, and scored ourselves a reusable Window component which we can call from anywhere in the app. Nice work, but there’s more to come… If we’re going to use the Preview Window again, we’ll probably need to use that Preview Button again too. Let’s see:
/** * AdFunded.views.Video.PreviewButton * @extends Ext.Button * Displays a Preview Window for the given video_id */ AdFunded.views.Video.PreviewButton = function(config) { var config = config || {}; Ext.applyIf(config, { text: 'Preview Video', iconCls: 'play', handler: function() { var win = new AdFunded.views.Video.PreviewWindow({video_id: config.video_id}); win.show(); } }); AdFunded.views.Video.PreviewButton.superclass.constructor.call(this, config); }; Ext.extend(AdFunded.views.Video.PreviewButton, Ext.Button); Ext.reg('video_preview_button', AdFunded.views.Video.PreviewButton);
Which leaves us with the following the the view:
items: [ { xtype: 'video_preview_button', video_id: id } ]
We’ve now gone from 34 lines to 6 (in the view at least), but the point is not about cutting out lines of code – it’s creating reusable components. We’ve added 20 lines overall this way but we now have two extra components that we can call on at any time (with minimal lines of code), safe in the knowledge that they will provide a consistent experience each time.
Works great Ed! Thanks!One comment about my own experience, however, you HAVE to specify your namespace you are creating your extension in, other wise you get a strange “[your name space] has no properties” error. This is easily fixed of course by inserting a Ext.namespace(‘[your name space]’); just before your extension code.
Thanks for the comment, angry_coder.I would usually have declared the namespace elsewhere (i.e. not in the class extension itself), so would not need to do so again while defining the class, but you’re right that is has to be declared somewhere!In this case the declaration would just look like:Ext.ns(‘AdFunded.views.Video’);
Excellent, accessible example. I’ve recently been creating some windows for filtering and confirmation and the example will probably be the logical conclusion once I’ve had time to refactor it. Your git source has been helpful, too.On another note, does crud_controller.js:86 work? I used it as an example for something similiar, but I had to use createDelegate to bind this and pass additional arguments to the Ext.Msg.confirm callback to actually get Ext.Ajax.request to fly…Congrats on your bra app. š
@Jason thanks for the comment.Are you referring to http://github.com/edspencer/ext-mvc/tree/master/controller/crud_controller.js#L86? I’ve not looked at that for a while but it looks like it’s missing a scope: this in the Ajax.request block…To be honest that code is so old (and crap) now that I’ve got no idea – there is a later branch at http://github.com/edspencer/ext-mvc/tree/v0.4, though the v0.5 branch I’m currently working on is vastly better… much cleaner JS and a MVC stack which feels much more like Rails.Give me a few weeks and I’ll do a blog series on it as I think it could help a lot of people out.
This is Excellent, this has helped me a lot… I tried to open YouTube video in Ext.Window ,it is opening up but when we close the window – Audio is playing background. Could you please help me on this one.Thanks,Vivek[http://www.developersnippets.com]
I’m the ExtJs newbie
You have done excellent example.
but wondering … what if I want to change the subclass attribute every time when use at some difference application, how to go about it.
Sorry for asking stupid question..
Thanks anyway.
Pingback: extjstutorial.org