ExtJS 5.1.1立即在ViewModel中触发绑定

问题描述 投票:4回答:4

好像我对绑定时间有一些误解。我有一个简单的组合框,其值绑定到viewmodel中的某个对象。选择新值,触发更改事件,在setValue方法之后触发,因此我的新值已经设置,但我的viewmodel尚未更新。什么时候我的viewmodel会更新?我找到了一些关于调度程序的信息,它说我需要运行notify()方法立即将更改应用于viewmodel,但它根本没有帮助我。

Ext.define('MyModel', {
    extend: 'Ext.data.Model',
    idProperty: 'foo',
    fields: [{
        name: 'bar',
        type: 'string'
    }]
});

Ext.define('MyViewModel',{
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.my',
    data: {
        testObj: {
            foo: null,
            bar: null
        }
    },
    stores:{
        combostore: {
            model: 'MyModel',
            data: [{
                foo: '1',
                bar: 'qwerty'
            },{
                foo: '2',
                bar: 'ytrewq'
            }]
        }
    }
});

Ext.define('MyViewController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.my',
    onChange: function() {
        var vm = this.getViewModel();
        vm.notify();
        console.log(vm.get('testObj.foo'));//supposed to be current value
    }
});

Ext.application({
    name : 'Fiddle',

    launch : function() {
        Ext.create('Ext.container.Viewport', {
            controller: 'my',
            viewModel: {
                type: 'my'
            },
            layout : 'vbox',
            items : [
                { 
                    xtype : 'combo',
                    valueField: 'foo',
                    displayField: 'bar',
                    queryMode: 'local',
                    bind: {
                        store: '{combostore}',
                        value: '{testObj.foo}'
                    },
                    listeners:{
                        change: 'onChange'
                    }

                }
            ]
        });
    }
});

这里也是小提琴:https://fiddle.sencha.com/#fiddle/r88

javascript extjs mvvm data-binding extjs5
4个回答
2
投票

我知道这是一个迟到的回应,但我认为这个问题仍然存在。看到这个小提琴:https://fiddle.sencha.com/#fiddle/2l6m&view/editor

基本上,我们的想法是您监听绑定变量而不是监听组合框选择更改(这会触发绑定变量的重新评估)。

关键代码在我为视图模型添加的构造函数中:

Ext.define('MyViewModel',{
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.my',

    // added this to enable the binding
    constructor: function () {
        var me = this;
        me.callParent(arguments);

        me.bind('{selectedItem}', function (value) {
            console.log('combobox selected item changed (bar value): ' + (value === null ? "null": value.get('bar')));
            console.log(me.getView().getController());
        });

        me.bind('{testObj.foo}', function (value) {
            console.log('combobox value (foo value): ' + value);

            // you can access the controller
            console.log(me.getView().getController());
        });
    },
    data: {
        testObj: {
            foo: null,
            bar: null
        },
        selectedItem: null,
    },
    stores:{
        combostore: {
            model: 'MyModel',
            data: [{
                foo: '1',
                bar: 'qwerty'
            },{
                foo: '2',
                bar: 'ytrewq'
            }]
        }
    }
});

这是视图(注意与选择的绑定):

Ext.application({
    name : 'Fiddle',

    launch : function() {
        Ext.create('Ext.container.Viewport', {
            controller: 'my',
            viewModel: {
                type: 'my'
            },
            layout : 'vbox',
            items : [
                {
                    xtype : 'combo',
                    valueField: 'foo',
                    displayField: 'bar',
                    queryMode: 'local',

                    bind: {
                        store: '{combostore}',
                        value: '{testObj.foo}',
                        selection: '{selectedItem}'

                    },
                    listeners:{
                        change: 'onChange'
                    }

                }
            ]
        });
    }
});

绑定选择不是必需的,但我将其作为另一个选项包括在内,因为有时您可能希望在绑定到列表的商店中存储其他数据。

我希望这有助于其他人。


0
投票

您不应该直接在viewmodel上调用notify。它是私人的:http://docs.sencha.com/extjs/5.0/5.0.1-apidocs/#!/api/Ext.app.ViewModel-method-notify

只需通过调用vm.setData({})来设置数据。

onChange: function(cb, newValue, oldValue) {
    var vm = this.getViewModel();

    console.log('newValue', newValue);
    console.log('oldValue', oldValue);
    this.getViewModel().setData({'testObj': {'foo': newValue}});
    console.log(vm.get('testObj.foo'));//supposed to be current value
}

从来没有考虑过以下示例,我使用公式来获取组合框的选定模型。看到我删除了监听器,添加了对组合框的引用并创建了一个公式以深入绑定到所选记录。

Ext.define('MyModel', {
    extend: 'Ext.data.Model',
    idProperty: 'foo',
    fields: [{
        name: 'bar',
        type: 'string'
    }]
});

Ext.define('MyViewModel',{
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.my',
    data: {
        testObj: {
            foo: null,
            bar: null
        }
    },
    stores:{
        combostore: {
            model: 'MyModel',
            data: [{
                foo: '1',
                bar: 'qwerty'
            },{
                foo: '2',
                bar: 'ytrewq'
            }]
        }
    },

    formulas: {
        currentRecord: {
            bind: {
                bindTo: '{myCombo.selection}',
                deep: true
            },
            get: function(record) {
                return record;
            },
            set: function(record) {
                this.set('currentRecord', record);
            }
        }
    }
});

Ext.define('MyViewController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.my',
    onChange: function(cb, newValue, oldValue) {
        var vm = this.getViewModel();

        console.log('newValue', newValue);
        console.log('oldValue', oldValue);
        this.getViewModel().setData({'testObj': {'foo': newValue}});
        console.log(vm.get('testObj.foo'));//supposed to be current value
    }
});




Ext.application({
    name : 'Fiddle',

    launch : function() {
        var vp = Ext.create('Ext.container.Viewport', {
            controller: 'my',
            viewModel: {
                type: 'my'
            },
            layout : 'vbox',
            items : [
                { 
                    xtype : 'combo',
                    reference: 'myCombo',
                    valueField: 'foo',
                    displayField: 'bar',
                    queryMode: 'local',
                    bind: {
                        store: '{combostore}',
                        value: '{testObj.foo}'
                    }/*,
                    listeners:{
                        change: 'onChange'
                    }*/
                },
                {
                    xtype: 'label',
                    bind: {
                        text: '{currentRecord.foo}'
                    }
                }
            ]
        });

        /* Just an example. You could also select records on the combo itself */
        vp.getViewModel().setData({'testObj': {'foo': '2'}});
    }
});

0
投票

推迟将是你的救世主:

onChange: function() {
    var vm = this.getViewModel();

    Ext.defer(function(){
       console.log(vm.get('testObj.foo'));//supposed to be current value
    },10,this);
}

0
投票

请使用select事件而不是change

我认为更改事件甚至在设置值之前就会触发。

© www.soinside.com 2019 - 2024. All rights reserved.