Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

mvvm - EXTJS 6.5 Binding store data in viewmodel to field in view

Unfortunately I don't know how to make an MVVM Modern app work in Fiddle so I'll have to post my code here, but here's a simple app that demonstrates the problem I'm having.

App.js

Ext.application({
    extend: 'simple.Application',

    name: 'simple',

    requires: [
        // This will automatically load all classes in the simple namespace
        // so that application classes do not need to require each other.
        'simple.*'
    ],

    // The name of the initial view to create.
    mainView: 'simple.view.main.Main'
});

app/Application.js

Ext.define('simple.Application', {
    extend: 'Ext.app.Application',

    name: 'simple',

    //my understanding is that I need to load my stores here in Application.js
    //as opposed to in the controller?
    requires: ['simple.store.barcodeInfoStore'],

    stores: ['barcodeInfoStore']

});

app/model/Base.js

Ext.define('simple.model.Base', {
    extend: 'Ext.data.Model',

    schema: {
        namespace: 'simple.model'
    }
});

app/model/barcodeInfoModel.js

Ext.define('simple.model.barcodeInfoModel', {
    extend: 'simple.model.Base',

    fields: [
        {name: 'barcode', type: 'string'},
        {name: 'status', type: 'string'}
    ]
});

app/store/barcodeInfoStore.js

Ext.define('simple.store.barcodeInfoStore', {
    extend: 'Ext.data.Store',

    alias: 'store.barcodeInfoStore',

    model: 'simple.model.barcodeInfoModel',

    data: {
        items: [//here I'm just loading some dummy data to start
                {barcode:'12345678',status:'GOOD'}
            ]
    },

    proxy: {
        type: 'memory',
        reader: {
            type: 'json',
            rootProperty: 'items'
        }
    }
});

/app/view/main/Main.js

Ext.define('simple.view.main.Main', {
    extend: 'Ext.form.Panel',
    xtype: 'app-main',

    controller: 'main',
    viewModel: {
        type: 'main'
    },

    items: [{   xtype: 'formpanel',
                reference: 'form',
                items: [
                    {   xtype:'textfield',
                        label: 'Barcode',
                        placeholder: 'Barcode',
                        name: 'barcodeField',
                        reference: 'barcodeField',
                        allowBlank: false,
                        autoComplete: false
                    },
                    {   xtype:'textfield',
                        label: 'Status',
                        placeholder: 'Status',
                        name: 'statusField',
                        reference: 'statusField',
                        allowBlank: false,
                        autoComplete: false
                    },
                    {   xtype:'displayfield',
                        label: 'Fixed Data Bound Field',
                        bind: {
                            //test display field bound to some hard coded data
                            //in my viewModel just to verify that that works
                            //(it does)
                            value: '{fixedDataBarcode}'
                        }
                    },
                    {   xtype:'displayfield',
                        label: 'Store Data Bound Field',
                        bind: {
                            //test display field that I want to bind to store data
                            //(this DOES NOT work)
                            value: '{myStore.barcode}'
                        }
                    },
                    {
                        xtype:'button',
                        text:'Update',
                        handler:'onUpdateClicked'
                    }
                ]
            }
    ]
});

app/view/main/MainController.js

Ext.define('simple.view.main.MainController', {
    extend: 'Ext.app.ViewController',

    alias: 'controller.main',

    //get a reference to my store and update the values in it
    //with the values from the form
    onUpdateClicked: function() {
        console.log('onUpdateClicked');
        var form = this.lookupReference('form');
        var formValues = form.getValues();

        var store = Ext.getStore('barcodeInfoStore');
        var data = store.getAt(0).data;

        data.barcode = formValues.barcodeField;
        data.status = formValues.statusField;

        console.log('Store Data Is Now ' + data.barcode + ', ' + data.status);
    }

});

app/view/main/MainModel.js

Ext.define('simple.view.main.MainModel', {
    extend: 'Ext.app.ViewModel',

    alias: 'viewmodel.main',

    //this is where I'm trying to get a reference to my store
    //so I can bind data to it's values, but am not sure of the correct way
    //to do this?
    stores:{
        myStore: {
            data: Ext.getStore('barcodeInfoStore')
        }
    },

    //this is just some hard coded data to verify that I can bind to
    //data in my viewModel
    data: {
        name: 'simple',
        fixedDataBarcode: '11111111'
    }
});

When I load my app I see the interface, and can see my 2 displayFields, and bound data from my hard coded data in the viewModel, but not seeing the "12345678" I was hoping to see from my store data

enter image description here

I then enter some values in the form fields and click UPDATE and can see that I'm in my controller's function and that the data has been updated, and this is where I'd expect to see my "Store Data Bound Field" in my form updated with the value 55555555

enter image description here

While this is just a simple app to demonstrate my problem, ultimately what I am trying to do is to receive a barcode into the barcode field, query a database via Ajax to get it's data, update the store with that data and display/use that data for further processing.

So I guess my questions are

  • Why doesn't this work as is - I'm sure I have something wrong if you can help me correct it?
  • Is this method the best way to approach what I'm trying to accomplish or is there a better way?

UPDATE: I made some progress. I changed my viewModel stores definition to

stores:{
        myStore: {
            //data: Ext.getStore('barcodeInfoStore')
            type: 'barcodeInfoStore'
    }
},

and added a formula

formulas:{
    getData: function(get){
        console.log('in getData');
        return Ext.getStore('barcodeInfoStore').first().data;
    }
},

and my form field binding to

{   xtype:'displayfield',
    label: 'Store Data Bound Field',
    bind: {
            value: '{getData.barcode}'
    }
}

and now when I load my form I see the bound data from the store enter image description here

The only issue now is that when I enter a barcode/status in my form and click UPDATE, which updates the data in the store, the data in the bound field doesn't update to the new data

enter image description here

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to update your custom property values as in your case you have taken getData. You are only updating store values and it is not reflecting the getData values. So you have to update as getData as same values.

In this FIDDLE, I have created a demo using your code and make some modification. I hope this will help you/guide you to solve your problem/requirement.

CODE SNIPPET

Ext.define('simple.model.Base', {
    extend: 'Ext.data.Model',

    schema: {
        namespace: 'simple.model'
    }
});

Ext.define('simple.model.barcodeInfoModel', {
    extend: 'simple.model.Base',

    fields: [{
        name: 'barcode',
        type: 'string'
    }, {
        name: 'status',
        type: 'string'
    }]
});

Ext.define('simple.store.barcodeInfoStore', {
    extend: 'Ext.data.Store',

    alias: 'store.barcodeInfoStore',

    model: 'simple.model.barcodeInfoModel',

    data: {
        items: [ //here I'm just loading some dummy data to start
            {
                barcode: '12345678',
                status: 'GOOD'
            }
        ]
    },

    proxy: {
        type: 'memory',
        reader: {
            type: 'json',
            rootProperty: 'items'
        }
    }
});

Ext.define('simple.view.main.MainModel', {
    extend: 'Ext.app.ViewModel',

    alias: 'viewmodel.main',

    stores: {
        myStore: {
            type: 'barcodeInfoStore'
        }
    },

    data: {
        formData: null
    },

    formulas: {
        setFormData: function (obj) {
            //Set formData value from myStore
            this.set('formData', this.get('myStore').first().data)
        }
    }

});

Ext.define('simple.view.main.Main', {
    extend: 'Ext.form.Panel',

    xtype: 'app-main',

    controller: 'main',

    viewModel: {
        type: 'main'
    },

    title: 'View Model example',

    items: [{
        xtype: 'textfield',
        label: 'Barcode',
        placeholder: 'Barcode',
        name: 'barcode',
        reference: 'barcodeField',
        allowBlank: false,
        autoComplete: false
    }, {
        xtype: 'textfield',
        label: 'Status',
        placeholder: 'Status',
        name: 'status',
        reference: 'statusField',
        allowBlank: false,
        autoComplete: false
    }, {
        xtype: 'displayfield',
        label: 'Store Data Bound barCode Field',
        bind: {
            value: '{formData.barcode}'
        }
    }, {
        xtype: 'displayfield',
        label: 'Store Data Bound Status Field',
        bind: {
            value: '{formData.status}'
        }
    }, {
        xtype: 'button',
        text: 'Update',
        ui: 'action',
        width: '100%',
        handler: 'onUpdateClicked'
    }]

});

Ext.define('simple.view.main.MainController', {
    extend: 'Ext.app.ViewController',

    alias: 'controller.main',

    /*
     * this function will fire on update button click
     * @param {Ext.Button} button
     */
    onUpdateClicked: function (button) {
        var form = button.up('formpanel'),
            formValues = form.getValues(),
            viewModel = this.getViewModel();

        //You need to update viewmodel properties to check binding
        viewModel.set('formData', formValues);
        console.log(`formData Is Now 
 ${Ext.encode(viewModel.get('formData'))}`);

        //If you need to update data inside store then you need to use below code
        viewModel.get('myStore').getAt(0).set(formValues);
        console.log(`Store Data Is Now 
 ${Ext.encode(viewModel.get('myStore').getAt(0).data)}`)
    }
});

Ext.define('simple.Application', {
    extend: 'Ext.app.Application',

    name: 'simple',

    //my understanding is that I need to load my stores here in Application.js
    //as opposed to in the controller?
    requires: ['simple.store.barcodeInfoStore'],

    stores: ['barcodeInfoStore']
});

Ext.application({
    extend: 'simple.Application',

    name: 'simple',

    requires: [
        // This will automatically load all classes in the simple namespace
        // so that application classes do not need to require each other.
        'simple.*'
    ],

    // The name of the initial view to create.
    mainView: 'simple.view.main.Main'
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...