Search code examples
javascriptmodel-view-controllerviewyui

How to change a subview using the YUI App framework


I'm creating an app using the YUI App framework for the first time. So I'm still trying to understand how it all works.

My app will be showing several views at the same time, this is done by using nested views. When navigating the app it should be possible to change only one of the (sub)views without having to re-render the parentview.

I have created a simple example here: http://jsfiddle.net/casperskovgaard/BDqjz/6/

The app will render a HomePageView containing two subviews. A menu view and a content view. From the menu view it is possible to change the content view.

Code that renders the homepage looks like this:

render: function () {
    Y.log('render homepage view');
    var container = this.get('container');

    container.setHTML(this.template());
    container.one('#menu').setHTML(new Y.MenuView().render().get('container'));
    container.one('#content').setHTML(this.get('content').render().get('container'));

    return this;
}

The content view will change if the route is changed.

As it is now HomePageView and both subview will re-render every time the route is changed.

How can I change it, so only the content view is re-rendered, when clicking the links in the menu view?

Also I'm a bit confused on how to use the container attribute on the subviews, any tips will be appreciated

-Casper


Solution

  • Based on further description in comment under first answer, I would still remove the MenuView and other subviews from the "views" property as it is really only used for views that will be made the "activeView" which they won't.

    I would make the HomePageView a "preserved" view and use the "callback" property to the options object passed to 'showView' to tell that view what content to be shown.

    So 'views' now looks like:

    views: {
        homePage: {type: 'HomePageView', preserve: true}
    }
    

    And your handler(s) looks like:

    handleFirst: function () {
        this.showView(
            'homePage',
            null,
            { 
                callback: function (view) { 
                    view.showContent(Y.FirstView); 
                }
            }
        );
    }
    

    And I added a method to HomePageView like so:

    showContent: function (ctr) {
        Y.log("HomePageView::showContent: " + ctr);
        var container = this.get('container');
    
        container.one('#content').setHTML((new ctr).render().get('container'));
    }
    

    That's the simplest case where it takes the constructor of the view to put into the content area and re-creates it each time, etc. There is no reason why the instance of HomePageView can't keep a cache of its subviews and only create them when needed, etc. Either way the key is that you can use a callback to manipulate the underlying view when it becomes the "activeView" at the top level. (Alternatively I've done this such that I fire an event on that view rather than passing something to it and then use an event handler on the view to do the dirty work, but I don't know how comfortable you are with custom events.)

    http://jsfiddle.net/brianjmiller/eP7s2/2/

    Hopefully take two works.