The Ext.ComponentLoader
is perhaps one of the least discussed and lesser known features that ExtJS provides. Maybe that’s because only a few know that it can simplify how you build applications. Before showing that in an example, first I’ll briefly introduce the Ext.ComponentLoader
class.
This class is available in ExtJS 4.0.0 and is used to load any content via Ext.Ajax
into a Ext.Component
. At the Component level, there’s a config Ext.Component.loader
which accepts a configuration object or an instance of a Ext.ComponentLoader
to load any remote content for the Component
.
Ext.create('Ext.Component', { loader: { url: 'content.html', autoLoad: true }, renderTo: Ext.getBody() });
The main configs are the connection ones which are passed to Ext.Ajax
and the renderer
config. Through renderer
, Component
knows how to render the loaded content, which can be:
- html: The response text will be added to the component as raw html, see Ext.Component#html
- data: The JSON data received from the response is passed to the Ext.Component#update
- component: The response is expected to be one or many Ext.Component configuration objects which are passed to Ext.container.Container#add
- custom: Very much like a renderer function, this custom function is used to parse and process the response so that you can configure the
Component
as desired.
If html, data or component don’t fit your needs, the custom approach allows you to render pretty much anything. For example, one can build a lazy Ext.menu.Menu
which will lazily load all of its menuitems
from the server. That can be done with the Ext.Component.loader
so when the user clicks on any first level menuitem of a Menu
, based on the given parameters, the loader
loads the menuitems
from the server and then the given renderer
builds your Menu
.
Ext.define('Ux.view.Menu', { extend: 'Ext.menu.Menu', xtype: 'mymenu' minHeight: 100, // Give some space to see the load mask loader: { loadMask: { msg : 'Loading...' }, url: '/api/load_tree', renderer: function(loader, response, active){ var success = true; var target = loader.getTarget(); var items = []; var data; var i,ln; try { data = Ext.decode(response.responseText).data; // Loop through the data and build the menuitems configs for (i = 0, ln = data.length; i < ln; i++) { items.push(target.getMenuItemConfig(data[i])); } } catch (e) { success = false; } // Insert the menuitems in the Menu if (success) { target.suspendLayouts(); if (active.removeAll) { target.removeAll(); } target.add(items); target.resumeLayouts(true); } //Return true if ok, to call the callback and fire 'load' event return success; } } });
The lazy loading can be done through the Ext.Config
and Ext.mixin.Bindable
mixin. The Ajax parameters are exposed as an evented Ext.Config
config so they can be bound through the Bindable
mixin at the Menu level:
menu: { xtype: 'mymenu', bind: { extraParams: '{myData.myMenuParams}' } }
Then we have a listener at the config level, so whenever the extraParams
changes, the menu loads the remote data and builds itself.
listeners: { extraparamschange: function (menu, value) { // If the menu is visible load the subitems, // if not load them at first menu show. if (menu.isVisible()) { menu.loadMenuItems(value); } else { menu.on('beforeshow', menu.loadMenuItems, menu, { single: true }); } } }, // Here you can pre-process your params before applying // them on the Loader applyExtraParams: function (myMenuParams) { if (Ext.isArray(myMenuParams)){ return { myMenuParams: myMenuParams[0] } } }, loadMenuItems: function () { this.getLoader().load({ params: this.getExtraParams() }); }
Lastly, in case you have to load the tooltips remotely, you can do it in the menu afterRender
:
getMenuItemConfig: function (rec) { return { text: rec.get('title'), afterRender: function () { Ext.Ajax.request({ url: '/api/mylazymenu/tooltip/?p=' + rec.get('aParam'), success: function (response) { if (response.status = 200) { this.setTooltip(response.responseText); } }.bind(this) }); } }; }
You can find the Fiddle here
Conclusion
You could use Ext.Ajax
to load your menu items but with the Ext.ComponentLoader
you can do it in an easier, simpler and cleaner way. This, by default, provides you some renderers
that you can use to build your Components content.
Vadim Popa
Related Posts
-
Custom Components in NativeScript
ul { list-style: circle outside; } There aren't too many things as satisfying as doing…
-
Custom Components in NativeScript
ul { list-style: circle outside; } There aren't too many things as satisfying as doing…