Blog.

Configuring ViewModel Hierarchy

If you haven’t yet read and understood article ViewModel Internals do it now, or the following may not make any sense to you. It is an advanced material.
See also the related example and download the complete source code.

Do we need it?

Perhaps not. For small applications that have a couple of views, one container with one “main” view model that is holding data, a few stores and a couple of formulas for needs of each and every view we do not need any hierarchy of view models.

single-viewmodel

But imagine an application with one or two hundreds of views. Do we still want to keep all data and stores in the main view model and let its code grow to thousands, many thousands of lines? Initializing stores, formulas and data also when the view using them is not currently visible or instantiated?

The easy solution then, right? Let’s put all “view-only” stores, data and formulas in their own view models that have lifetime identical to the lifetime of their views.

many-viewmodels

Well, are almost there. Not quite, but almost. The problem we have now is how to bind data between view models. For example, selecting a row in a grid should populate a form with detail data. But both grid and form have their own view models. We would like to publish the grid selection up to the main view model to which we could bind the form fields, yet we would like to keep the grid store configuration in the “local” grid’s view model.

When we need it, how to implement it?

To demonstrate, let take the following simple example.
Selecting a row of the grid causes that the underlying record from the grid store populates the detail form on the right.

Right after running sencha generate view ... we have this structure:

Initial Views and View Models
Initial Views and View Models

There are no relations between views and their view models other than that views use their view models. It is just a starting point for us to start configuring data binding and publishing.

The first thing to configure in the grid view model is the store. And, because we want the grid to publish its selection, we set a “reference” in the grid view. If a reference for the grid is configured, the selected record is automatically published.

Initial Views and View Models
Configured store and reference

Whereto is it published? To the grid’s view model. The missing ingredient is how to get the selected record up to the main view model so that we could bind the form fields.

Initial Views and View Models
Publishing a value upwards
For that we need to do two things:

  1. In the main view model, configure the object that will hold the currently selected customer:
    data: {
        // We need an object here as view models use prototype chain
        // so the 'current' object is inherited by lower view models
        // We bind to {current.customer} throughout the application
        current:{
            customer:null
        }
    } // eo data
  2. In the grid view model, define the formula that does the trick:

    formulas:{
        // current customer is bound to automatically published selection
        currentCustomer:{
             bind:'{customersList.selection}'
            ,get:function(customer) {
    
                // this is core of the trick
                // whenever selection changes, this method is called
                // so we also update current.customer that is defined
                // in the main view model
                this.set('current.customer', customer);
                return customer;
    
            } // eo function get (currentCustomer)
        } // eo currentCustomer
    
    } // eo formulas

The rest is peanuts, we just bind the form fields to “{current.customer.[field name]}” and we are done. Of course, we can utilize the form view model to calculate some derived data for us, such as valid and dirty states.

Initial Views and View Models
Binding form fields and status

I believe that this technique helps you to code better, robust and modularized application without a spaghetti code.

See also the related example and download the complete source code.
saki
Follow me:
Latest posts by saki (see all)

6 Responses

  1. My get handler for the formula never gets fired. I am binding to the panel width property using reference? What am i doing wrong? Am i missing something obvious?

  2. Hi Saki,
    I have a question why Selected record is automatically published to View model? How just by specifying reference selected record are published to view model.

    Please let me know the mechanism behind this

    Thanks

  3. Thanks for the explanation. It seem this pattern is susceptible to automation so hopefully future releases will make this simpler or, at least, obvious.

    Bill

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Enter your username and password to log into your account. Don't have an account? Sign up.

Want to collaborate on an upcoming project?