Get a reference to another view in a ViewController

285 views
Skip to first unread message

Alper Gokcehan

unread,
Nov 4, 2013, 1:15:39 PM11/4/13
to def...@googlegroups.com
Hi,

I have a viewport that has a toolbar and a container (MainPanel) in vbox layout. When clicking on a button in the toolbar, I want to replace the MainPanel container with another panel.

Without DeftJS, I can do this by adding the following lines to the Toolbar controller which would give me the reference to the MainPanel by calling this.getMainPanel():

refs : [
    {
        ref : 'mainPanel',
        selector : 'app-container'
    }
],
    
I couldn't figure out how I can do this with DeftJS. I tried injecting the MainPanel view into the Toolbar Controller:

inject: [
    'mainPanel'
],

By adding the 'mainPanel' to the dependency provider in the IoC configuration in the Application.js file:

buildInjectorConfiguration: function() {
    var config;
    config = {
        appConfig: {
            className: "myApp.config.AppConfig",
            parameters: [
                {
                    environment: myApp.config.AppConfig.PRODUCTION_ENV
                }
            ]
        },
        mainPanel: "myApp.view.MainPanel"
    };
    return config;
},

    
With the above code, I can access the MainPanel view using mainPanel() method, but this actually creates instance of the view instead of referencing the existing one. 

I need to get a handle to the existing MainPanel so that I can switch it's content. How can I get my viewController to access MainPanel view? Is the only way doing this through component query?

Thanks!



Here is my code:

view/MainPanel.js

Ext.define('myApp.view.MainPanel', {

    extend: 'Ext.container.Container',

    alias: 'widget.view-MainPanel',

    requires: [
        'myApp.controller.MainPanelController',
        'myApp.view.Dashboard'
    ],

    controller: 'myApp.controller.MainPanel',

    initComponent: function() {
        Ext.applyIf(this, {
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            items: [
                {
                    xtype: 'view-Dashboard',
                    flex: 1
                }
            ]
        });
        return this.callParent(arguments);
    },

    changeView: function(component) {
        Ext.suspendLayouts();
        this.removeAll(true);
        this.add(component);
        Ext.resumeLayouts(true);
    }
});


view/Toolbar.js

Ext.define('myApp.view.Toolbar', {
    
    extend: 'Ext.toolbar.Toolbar',

    alias: 'widget.view-Toolbar',

    requires: ['myApp.controller.Toolbar'],

    controller: 'myApp.controller.Toolbar',

    initComponent: function() {
        Ext.applyIf(this, {
            enableOverflow: true,
            defaults: {
                scale: 'large'
            },
            items: [
                {
                    xtype: 'button',
                    html: 'Show Panel',
                    itemId: 'toolbar1'
                }
            ]
        });

        return this.callParent(arguments);
    }
});

controller/Toolbar.js

Ext.define('myApp.controller.Toolbar', {

	extend: "Deft.mvc.ViewController",

    requires: ['myApp.view.MainPanel'],
    
    control: {
        toolbar1: {
            click: 'showPanel'
        }
    },
    
    init: function() {
        return this.callParent(arguments);
    },
    
    showPanel: function() {
        this.getMainPanel().changeView({ //need to get getMainPanel() method to give me the reference to the MainPanel view.
            xtype : 'view-appPanel',
            flex : 1
        });
    }

});

Brian Kotek

unread,
Nov 4, 2013, 2:17:54 PM11/4/13
to deftjs
Hey Alper. You don't inject views, only dependencies you've set up on the Injector. Accessing views is covered in the docs at https://github.com/deftjs/DeftJS/wiki/Accessing-Views. Let me know if that gives you the info you're looking for.


--
Deft JS home page: http://deftjs.org/
Wiki: https://github.com/deftjs/DeftJS/wiki
For rules and tips on asking questions on the Deft JS mailing list: https://github.com/deftjs/DeftJS/wiki/Asking-Questions-on-the-Mailing-List
---
You received this message because you are subscribed to the Google Groups "Deft JS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to deftjs+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/deftjs/CAH7WnMQq_zKoRgavea9NJWvjkQ%2BPvT5Yd_Z2YH9f-Mmq%3DPNjbQ%40mail.gmail.com.
For more options, visit https://groups.google.com/groups/opt_out.

Brian Kotek

unread,
Nov 4, 2013, 2:26:53 PM11/4/13
to deftjs
Ah, now I think I see what you're asking. From your Toolbar view controller you want access to the MainPanel. Since the selectors are relative to the view being managed, the Toolbar controller won't locate the MainPanel, since MainPanel isn't a descendant of the Toolbar view.

So one option is to use your own component query that starts at the display root (Viewport).

The better option is to have the toolbar be a child of the MainPanel. A Viewport is really only intended to have one child anyway. If the Toolbar is a descendant of the MainPanel, you'll be able to access both the Toolbar and MainPanel views from the MainPanel controller.

Let me know if that makes sense.

Brian Kotek

unread,
Nov 4, 2013, 2:33:37 PM11/4/13
to deftjs
You can see an example of this in the Phoenix app, where the controller for the grid also handles events from the grid's toolbar: https://github.com/deftjs/Examples/blob/master/phoenix-cmd/app/controller/ScenarioGridController.js

Keep in mind that every view in your app does not necessarily need a dedicated ViewController. That could potentially lead to a lot of ViewControllers! In many cases, a single ViewController can manage a set of views (such as a Panel and it's Toolbar). Obviously, it's a design choice, and you don't want to go too far and end up with some SuperMegaViewController that's 10,000 lines long and manages 50 views. So you want to break things up where it makes sense. Just point out that you don't HAVE to have a view controller for every single view.

Alper Gokcehan

unread,
Nov 4, 2013, 3:40:50 PM11/4/13
to def...@googlegroups.com
I chose to go with the 'better option' and my problem resolved. Thanks!


Chad Glendenin

unread,
Nov 4, 2013, 4:24:14 PM11/4/13
to def...@googlegroups.com
I'm not sure if this will be helpful, but if there are only a couple of top-level views that you need to switch between, you don't necessarily need to destroy and create instances of them every time. I have a couple Sencha Touch apps that have just a few main views, and what I do is set up a top-level container with a 'card' layout, and then, where needed, I inject a NavigationService object that has methods like showHelpScreen() or showMenu() to wrap the "cardLayout.setActiveItem(2)" stuff in something more meaningful.



Alper Gokcehan

unread,
Nov 4, 2013, 4:47:05 PM11/4/13
to def...@googlegroups.com
Hi Chad,

Thanks for the suggestion. Can you provide me any example on how to use the navigation service with Deft so that I can call service methods to switch content on my Toolbar actions?

Thanks,
Alper


Brian Kotek

unread,
Nov 4, 2013, 4:56:46 PM11/4/13
to deftjs
Another option (which may be similar to what Chad is talking about) is to inject an object and use events to trigger changes in other parts of the app. The Phoenix app shows this with "context" objects:




Chad Glendenin

unread,
Nov 4, 2013, 5:05:15 PM11/4/13
to def...@googlegroups.com
I have class like this:

Ext.define('App.service.NavigationService', {
  showAbout: function () {
    Ext.Viewport.setActiveItem(3);
  },
  showSettings: function () {
    Ext.Viewport.setActiveItem(2);
  },
  …
});

Then if the number of items or their order changes, I only have to change it in one place. In other places in the app, I inject the nav object to access those methods:

Ext.define('App.controller.SettingsViewController', {
extend: 'Deft.mvc.ViewController',
inject: ['navigationService'],

config: {
navigationService: null
},

control: {
backButton: {
tap: 'onBackButtonTap'
}
},

init: function () {
return this.callParent(arguments);
},

onBackButtonTap: function () {
this.getNavigationService().showHome();
}
});

In app.js's launch() method, I configure Deft's Injector and then call Ext.Viewport.add([{xtype: 'home'}, {xtype: 'settings'}, …]);



Reply all
Reply to author
Forward
0 new messages