PDA

View Full Version : MVC: How to properly create multiple instances of the same view, with data-binding



DigiDog
16 Apr 2012, 12:21 PM
Hi,

I've asked this question (http://stackoverflow.com/questions/10174703/extjs4-store-per-panel-instance)over on StackOverflow (see for discussion), but I think I'd like more feedback, I'm sure there's a proper way of doing this.

I want to be able to create multiple instances of data-bound tabs, that use the same controller and the same model for everything.

Should each have it's own store? I've only started, but I'm creating new tabs like this and not sure it's the right way (and how to proceed).

The same question from SO, without the confusion:

I have a tabpanel with multiple instances of the same component (let's call it product), each should call the server when it's opened, with an id parameter. Right now, in order to create these tabs - I use this in the Product controller Which creates a new instance of a view, but I feel like it's really incorrect.



createMainView: function (opts) {
return Ext.widget("productDisplay", opts);
}


I call it from my "main" controller, like this:


var tab = this.application.getController("Products")
.createMainView({ productId : id, closable: true })

tabs.add(tab);
tabs.setActiveTab(tab);


What's the correct way to properly use multiple instances of a view, each having an instance of one store and behavior (via the controller).

Can I use one named store for them (with a js file under app/store/product.js)?

Should I manually call load on the store from the controller (to pass the productId), or is there a nicer way?

Thank you!

vietits
16 Apr 2012, 4:46 PM
The way you create view instance is OK. To make each view independent with others, you should make sure each view has its own store instance.

slemmon
16 Apr 2012, 5:27 PM
When you define the productDisplay widget you can set the store using the type config to ensure each instance of productDisplay has its own instance of the store.

When you define your store use (alias: 'store.products') where products is whatever alias you want to use for each instance of productDisplay.

Then when you define productDisplay you can use store: { type: 'products' }. Just make sure the store is listed in the stores: [] property of your controller so it gets registered at the time the app starts up.

Since productDisplay is loading the store with its own productId you could have your controller listen for the productDisplay's afterrender event like:


afterrender: function (cmp) {
cmp.getStore().load({
params: {
productId: cmp.productId
}
});
}

DigiDog
16 Apr 2012, 6:45 PM
@slemmon, that looks very close to what I imagined the solution would look like, MVCish and delicious :)

One question though, the guy who responded to me on stackoverflow pointed out that maybe what I need is not a store per instance, but a record (since I only load a single "product").

Does that make any sense? It got me thinking... If this view was not a tab, but a sub-view (like a dynamically added panel, like in the nested loading (http://dev.sencha.com/deploy/ext-4.0.0/examples/app/nested-loading/nested-loading.html) example), I wouldn't think I need a store, because then I'd have to somehow manually bind the first record to the view each time (right?)

slemmon
16 Apr 2012, 6:55 PM
I'm not 100% sure. I've not worked with the models directly before. I'd have to do some research on that to see how that works. If the panel is not a grid or something with a store then even the type thing probably won't work exactly. I suspect you'll need to load a product record and then bind it to your panel one way or another either way unless your panel is of type grid or form.