PDA

View Full Version : Dynamically loading application script and hosting it in existing ExtJs container



Dhugal
31 Mar 2011, 6:40 AM
Hi All,

Over the past months I have started to integrate ExtJs into an existing ASP.NET MVC application. With this in mind my experience is somewhat limited so forgive me if I this is a basic question.

What I currently have is forms that are built using standard HTML input's etc. and JQuery tabs. The tabs are set up to load their content on the fly (ajax) and the server side code currently returns a HTML fragment to be shown in each tab. In some cases I load ExtJs components within these fragments via script which is also placed in the new HTML fragment.

This all works but I am looking to re-do the interface using purely ExtJs but I am confused about how to load a tabs content on the fly when the content will be an ExtJs Panel and who's layout etc. is returned from the server.

To clarify, I understand how to add panel to a tab, but what I don't have a grasp on is how you load script from the server which contains the code to create the new panel, execute that code and have the panel appear within the tab.

If the above isn't clear and example may help. Let's say the user is viewing an "Order"... the main details will be shown in an ExtJs form on the first tab, then there will be a secondary tab titled "Order Lines". When the user clicks this tab a request will be made to the server which will return the script to generate an ExtJs grid panel to show the relevant Order Lines in this second tab.

The layout, buttons, columns etc. of this grid can vary for each user, or each parent "Order" record and the code to handle this variance is on the server.

What I need to do is load the script for the content of this second tab, somehow tell it what tab it is being loaded into, and then execute it.

Can anyone give me any pointers?

Thanks.

Screamy
31 Mar 2011, 11:13 AM
I think the general usage pattern with Extjs is to load up all of the .js files you'll need in your application's home/index page, then call/instantiate objects as needed. How you architect the ExtJs objects in your .js files will directly affect how your app performs, memory utilization, etc.

I use the 'composition' style of object creation in my .js files, where you call a function to return new objects of the requested type. This way, no objects are 'newed' at load time; only after you call the function to retrieve them.

As a case in point, here's my abbreviated 'login.js' file which 'composes' and returns a login window/form. This sample uses namespacing, where I always declare global namespaces up front, prior to registering all of my .js files:

In this case, assume that Ext.ns("myApp.get") has already been called:



myApp.get.loginWindow = function() {
var form = new Ext.form.FormPanel({
monitorValid: true,
padding: 5,
ref: 'form',
items: [{
xtype: 'textfield',
allowBlank: false,
fieldLabel: 'Employee ID',
name: 'employeeId'
},{
xtype: 'textfield',
allowBlank: false,
fieldLabel: 'Password',
name: 'password'
}],
buttons: [{
text: 'Login',
formBind: true,
handler: function() {
form.getForm().submit({
url: 'login.action',
success: function(frm, action) {
// etc.
},
failure: function(frm, action) {
// etc.
}
});
}
}]
});

var win = new Ext.Window({
autoHeight: true,
title: 'Login',
width: 350,
items: [form]
});

return win.show();
};


When I need to show the login window, I just do this:



myApp.get.loginWindow();


There are other architectural styles to be had, but I like this method for building app-specific pieces of functionality.

I'm in the Java world, so I wrote a custom Ant build script which also concatenates all of my .js/.css files into one, calls YUICompressor to minify/obfuscate and shoves the end result files into my app's WAR. This helps eliminate the problem of loading lots of little .js/.css files during application startup.

Dhugal
31 Mar 2011, 11:10 PM
Hi Screamy,

Thanks for your response.

I understand where you are coming from and I have seen this set up before but I am not sure you have picked up what I am getting at.

Essentially I can't bundle all of my ExtJs components/classes into a single javascript file because their configuration is determined on the fly.

In my post I gave the example of an order form and the associated order lines grid. There is a load of code in the server side application that will determine how the order lines grid should look and behave based upon which user is viewing it, and which parent order they are viewing.

At present when the Order Lines tab is clicked Jquery requests the content from the server... the server side code will determine things like:

1) This order has been closed so the grid should be read only.
2) The current user is not an admin so the delete button should be hidden.
3) This related customer is on hold due to unpayed invoices so display a warning against the order lines etc.

With this in mind I can't create a static class in a JS file for the order lines grid because every time it's viewed it may change.

What I have at the moment is code the code on the server side that generates the javascript to create the grid with the relevant configuration but it just loads it within a HTML fragment, where as I want it to be hosted in the tab.

I need a way to be able to say - hit a URL, get the resulting script, execute it and put the resulting grid/panel in this tab.

Screamy
1 Apr 2011, 6:05 AM
Ah... sorry for the misunderstanding.

To handle similar situations, I've added 'afterrender' listeners on any components which needed to be dynamically manipulated. Each afterrender event fires off an Ajax request which performs a check to see if the component should be disabled or otherwise manipulated in some way.

I use the Spring framework with Spring Security on the back-end, so all requests have access to the security principal and role information, which obviously helps a lot when determining how an Ext component's state should be modified. Each request would return a standard block of JSON something like:



{
disabled: false,
canEdit: true,
<...>
}


The afterrender code would evaluate these settings and modify the component accordingly.

Another approach I considered (and abandoned) was creating a back-end "Ext Controller", which would stream the appropriate Ext object JSON configs to a client, based on their security role. It was a pain storing/manipulating the JSON config on the server side and ended up obfuscating problems, so I dropped the idea.

griffiti93
1 Apr 2011, 6:16 AM
I wrote BootstrapJS (http://code.google.com/p/bootstrapjs/) a few years back and have used it in production on 4 major products with great success. It supports caching on a per file level as well as defined boot groups. It also supports a cool splash screen while loading libraries.

Everything runs from index.html and there is no JS includes or HTML. Literally an empty <body /> tag. If any of this interests you, give me a shout sometime. I'd be happy to share how I approach RIA development.