10

I'm using Sencha Touch for a mobile app and am using the MVC functionality in it. I like Sencha quite a bit but I'm having a little trouble when it comes to passing data from one 'screen' to the next using the controller.

There's a "record" property associated with a number of the Sencha widgets --indicating the currently selected record in an Ext.list for instance-- and for some reason I can't quite get there as to how to pass something like that from an Ext.Panel to another one.

For instance, I have an Ext.Panel with data in it from an Ext.Store, including an address. I have another Ext.Panel that will show a map. I need to pass this address to the map's panel, but am not sure how. Here's what I'm trying from the first panel:

                listeners: {
                'tap': function () {
                    Ext.dispatch({
                        controller: app.controllers.establishments,
                        action: 'showMap',
                        id: record.getId(),
                        data: record.data
                    });
                }

I'm floundering a bit as you can see, trying to use both an 'id' and 'data' config option in the controller in an attempt to get data to the map panel, by any means necessary.

I don't necessarily need a answer for this specific problem, but if you had suggestions on how to do this in general-- basically, best practices for passing data from one screen to the next.

If it helps, I'm basing my app's structure on a nice MVC tutorial by Mr. Pearce at Sencha:

http://www.sencha.com/learn/Tutorial:A_Sencha_Touch_MVC_application_with_PhoneGap

Thanks much!

larryq
  • 15,713
  • 38
  • 121
  • 190

4 Answers4

6

I think you're on the right track with Ext.Dispatch. The parameters you add in the Dispatch options object are passed to the action method on the controller.

E.g.

showMap: function(options){ 
               var id = options.id; 
               //load data based on the id and pass it to your map
               ...
         }

I also think you should set the historyUrl on the Dispatch options object so that if they refresh the page the id will still get sent to the controller action.

Jason Freitas
  • 1,587
  • 10
  • 18
3

I am not too familiar with this MVC pattern but I have a lot of experience with ExtJS and in my opinion the best way for components to communicate is with events. In your example you would create an event on the Panel like 'addAddress' and the Map would listen for that event. And when the address was set in the panel you would call.

this.addEvent('addAddress');

this.fireEvent('addAddress', this, address);

and the map would have a listener like

onAddress: function(panel, address) {
   // do something with the address
}

and in your top level app you would add the listener.

app.mon(panel, 'addAddress', map.onAddress, this);

Typically it's best for your components together this way so that the Panel isn't dependent on the Map and vice-versa

Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • 1
    IMHO the views shouldn't have knowledge of each other. The controllers should be the one handling events and redirecting to another view. The only events Views should listen for are Model events so they can know when to update their data. – Jason Freitas Mar 03 '11 at 00:30
  • @Jason Freitas They don't have knowledge of each other. The main app object has knowledge of its child components and wires them together. The addAddress event could notify any number of different components that might want to do something with the address. – Robby Pond Mar 03 '11 at 03:20
  • @Robby Pond Good point, but I wonder how complex it would get as you add more views. Another nice thing about using Ext.Dispatch and the historyUrl is that the back button still works. – Jason Freitas Mar 03 '11 at 05:13
  • One more point is that sencha recommends destroying components (views) if they're not being shown, at least for sencha touch apps, which would prevent the panels from handling the events directly. The recommendation (and others) is covered here http://vimeo.com/17699976 – Jason Freitas Mar 03 '11 at 05:39
  • @Jason Freitas Thanks I'll check that out. Like I said I have zero experience using Sencha Touch but tons with ExtJS. I just assumed most of the same stuff would apply. – Robby Pond Mar 03 '11 at 12:45
  • Thanks for the discussion on this gentlemen. It's informative. Robby, I appreciate your tips on the ExtJS event handling best practices. – larryq Mar 03 '11 at 18:25
0

Answering a very old question, I suppose with the current versions of Sencha touch (2.2+) we have an alternate method, which I kind of prefer. Here it is for your evaluation.

Alternative is to use the routes feature of the controllers.

NOTE: Ext.Dispatch is deprecated in Sencha Touch 2.2, if you still want to use the dispatch method you need get the controller and call the method on it as explained here. How to pass data among the screens in sencha touch2.0?

First you define the routes a controller is interested in.

Ext.define('My.controller.Profile', {
extend: 'Ext.app.Controller'
,config: {
    routes: {
        'products/:id': 'showProduct'
    }
}
,showProduct: function(id) {
    console.log('Load and Show product... ' + id);
}

});

Next you create a link which has a url of this format as the href:

<a href="#products/1234">View Product</a>

Clicking the link will invoke the Product controllers showProduct method with id set to 1234.

Or if you wish to do this programmatically you could write:

location.hash = "products/1234";

which will have the same effect.

I think this is kind of clean, loosely coupled and has less dependency of framework internals. Open for ideas. :)

Community
  • 1
  • 1
BuddhiP
  • 6,231
  • 5
  • 36
  • 56
0

A better solution might be restructure your MVC to eliminate the need to pass records around different views. For example, making different view component share the same store, whose reference is made accessible from anywhere needed.

Usually I'd put the reference of stores used across different views in locations such as App.controllers.data nor directly under App (which is really just part of controller anyway).

Daniel Duan
  • 2,493
  • 4
  • 21
  • 24