Skip to content

alsolonets/extjs-mvvm-extensions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 

Repository files navigation

Extensions for custom components with a ViewModel.

  • Ext.vmx.mixin.Bindable
  • Ext.vmx.app.SplitViewModel

Ext.vmx.mixin.Bindable

Outside binding

Allows an outer component to bind to a component with own ViewModel. For instance, this is common when you extend from a Grid with a ViewModel inside.

Ext.define('MyGrid', {
    extend: 'Ext.grid.Panel',
    xtype: 'mygrid',

    viewModel: {

    }
});

Without the extension you aren't able to bind to it's selection from the outside (EXTJS-15503):

Ext.define('MyPanel', {
    extend: 'Ext.panel.Panel',
    
    viewModel: {

    },

    items: [{
        xtype: 'mygrid',
        reference: 'mygrid'
    }, {
        xtype: 'textfield',
        fieldLabel: 'Selected record',
        /*
        Won't work because of the viewModel inside 'MyGrid'.
        Use 'Ext.vmx.mixin.Bindable' to fix.
        */
        bind: '{mygrid.selection.name}'
    }]
});

Self binding

Allows to make a bind between component's configuration properties and it's inner components:

Ext.define('MyGrid', {
    extend: 'Ext.grid.Panel',
    xtype: 'mygrid',

    viewModel: {

    },
    
    config: {
        readOnly: false
    },

    publishes: ['readOnly'],

    tbar: [{
        text: 'Add',
        itemId: 'addButton',
        bind: {
            disabled: '{readOnly}'
        }
    }, {
        text: 'Remove',
        itemId: 'removeButton',
        bind: {
            disabled: '{readOnly}',
            text: 'Remove {selection.name}'
        }
    }]    
});

Demo

Full demo abailable at https://fiddle.sencha.com/#fiddle/1si5

Limitations

No known issues. Backward compatible. Keep in mind Sencha's recommendations: Don't nest data objects more deeply than necessary.

Usage

Ext.application({
    requires: [
        'Ext.vmx.mixin.Bindable'
    ]
});

Ext.vmx.app.SplitViewModel

Allows you to:

  • Define non-unique data field names among ViewModels
  • Reference to a parent ViewModel from a child

This extension needs in a more detailed explanation. Imagine you have two components, one is nested into another. They both have ViewModels. And both of these ViewModels have a color data field. You want to use configuration properties to control component's state. How would you bind the inner component's color config to the outer component's color? If you try, you would see that the binding doesn't work as far as names are not unique. https://fiddle.sencha.com/#fiddle/1so5

Seems we have to use different names for ViewModels' data fields. E.g. innerColor and outerColor. Obviously this is not convinient and doesn't guaranee uniqueness.

So here is the SplitViewModel extension that internally gives unique names to the data fields of a ViewModel. As the result ViewModels never interfere. To complete our example we are going to to make an explicit back-reference binding as shown:

Ext.define('Fiddle.view.OuterContainer', {
    // ...
    
    viewModel: {
        name: 'outercontainer',
        data: {
            color: null
        }
    },
    
    // ...

    items: [{
        xtype: 'innercontainer',
        bind: {
            color: '{outercontainer.color}'
        }
    }]
});
  1. We gave a name to the outer ViewModel since it's anonymous (in the same file). Either way the name would be taken from the alias automatically, e.g.

    alias: 'viewmodel.outercontainer'.

  2. We gave an explicit back-reference to the outer ViewModel:

    color: '{outercontainer.color}'

Demo

Try it https://fiddle.sencha.com/#fiddle/1so9

Pros

ViewModels are now isolated from each other. Developers are able to create independent views using both ViewControllers and ViewModels with no worrying about the ViewModels interference. With this extension binding becomes similar to a circuit boar wiring. Very predictable.

Limitations

If you had nested views both with ViewModels like in example above, then you must add an explicit back-reference to your bindings where necessary. Even if property names are unique. All you have to do is to prefix the binding expression with ViewModel's type or name.

Usage

Ext.application({
    requires: [
        'Ext.vmx.app.SplitViewModel'
    ]
});

Combining extensions

You are going to have the best results with both extensions included. Take a look at this example

https://fiddle.sencha.com/#fiddle/1sod

There are no handlers. Everything is done with a declaration syntax. Component's state is controlled by configuration properties but the internals are bound via ViewModel. This is great. I wish Sencha would have done this by default.

About

Ext JS MVVM extensions

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published