asp.net-web-apimvvmextjssencha-cmdextjs-grid

How to sync my Store when I update the bounded record using form (onUpdateClick). I'm using Extjs 7.5 (Sencha CMD)


This is my first time using a javascript framework, I would like to implement MVVM in my EXT JS application and the data is coming from my WEB API (ASP.NET FRAMEWORK).

My problem is that, I don't seem to understand how to fully use viewModel which looks up to my store. I successfully bound my ViewModel in my grid but now I don't know how to update the selected record using a form (modal) and sync my store (send update request through API)

I have a feeling that I'm doing it the wrong way. I don't know how to do this in fiddle so I'll just paste my code here.

  1. Genre.js [Model]

Ext.define('VAM2.model.Genre', {
    extend: 'VAM2.model.Base',
    alias: 'model.genre',
    fields: [
        {name: 'GenreId', type: 'int'},
        {name: 'Code',  type: 'string'},
        {name: 'CreatedBy',  type: 'string'},

    ]
});

  1. Genre.js [Store]

Ext.define('VAM2.store.Genre', {
    extend: 'Ext.data.Store',
    alias: 'store.genre',
    model: 'VAM2.model.Genre',
    autoLoad: false,
    pageSize: 10,
    storeId: 'GenreId',

    proxy : {
        type : 'rest',
        actionMethods : {
           read : 'GET' 
        },
        cors:true,
        url: 'https://localhost:44332/api/Genre/GetGenresExtJs',
        api:{
            create: 'https://localhost:44332/api/Genre/CreateGenreExtJS',
            read: 'https://localhost:44332/api/Genre/GetGenresExtJs',
            update: 'https://localhost:44332/api/Genre/EditGenreExtJS',
            destroy: 'https://localhost:44332/api/Genre/CreateGenreExtJS'
        },
        useDefaultXhrHeader: false,
        reader: {
           type : 'json',
           headers: { 'Accept': 'application/json' },
           allDataOptions: {
                associated: true,
                persist: true
            },
           rootProperty : 'data',
           totalProperty: 'total'
        },
    }

});

  1. GenreViewModel.js - I'm not sure if this is okay but the read is working

Ext.define('VAM2.view.genre.GenreViewModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.genre',

    requires:[
        'VAM2.model.Genre'
    ],

    stores: {
        myGenres : {
            model: 'VAM2.model.Genre',
            autoLoad: true,
            proxy : {
                type : 'rest',
                actionMethods : {
                   read : 'GET' 
                },
                cors:true,
                url: 'https://localhost:44332/api/Genre/GetGenresExtJs',
                api:{
                    create: 'https://localhost:44332/api/Genre/CreateGenreExtJS',
                    read: 'https://localhost:44332/api/Genre/GetGenresExtJs',
                    update: 'https://localhost:44332/api/Genre/EditGenreExtJS',
                    destroy: 'https://localhost:44332/api/Genre/CreateGenreExtJS'
                },
                useDefaultXhrHeader: false,
                reader: {
                   type : 'json',
                   headers: { 'Accept': 'application/json' },
                   allDataOptions: {
                        associated: true,
                        persist: true
                    },
                   rootProperty : 'data',
                   totalProperty: 'total'
                },
            }
        }
    },

    data:{
        title:'Sample Binding'
    },
        
    formulas: {
        currentRecord: {
            bind: {
                bindTo: '{groupGrid.selection}', //--> reference configurated                         
                                                //--> on the grid view (reference: groupGrid)
                deep: true
            },
            get: function(record) {
                return record;
            },
            set: function(record) {
                if (!record.isModel) {
                    record = this.get('records').getById(record);
                }
                this.set('currentRecord', record);
            }
        }
    }
    
});

  1. View -- This is where it gets confusing. I don't know how to put the bounded data from grid to a form modal and then save and sync my store.

Ext.define('VAM2.view.genre.GenreList', {
    extend: 'Ext.container.Container',
    xtype: 'myGenreList',

    requires: [
        'VAM2.view.genre.GenreController',
        'VAM2.view.genre.GenreViewModel',
        'Ext.grid.column.Boolean',
        'Ext.form.field.Checkbox',
        'Ext.form.field.TextArea',
        'Ext.form.field.Text'
    ],

    controller: "genre",
    viewModel: {
        type: "genre"
    },
    width:'100%',    
    layout: {
        type: 'vbox',
        pack: 'start',
        align: 'stretch'
    },
    style: {
        backgroundColor: '#f5f5f5'
    },

    items: [{
        xtype: 'grid',
        reference: 'groupGrid', //--> used in the viewmodel,
        bind: {
            title: '{title}',
            store: '{myGenres}'
        },
        columns: [{
            text:'GenreIdField',
            id:'GenreIdField',
            dataIndex:'GenreId',
            hidden:true
        },{
            text: 'Code',
            dataIndex: 'Code',
            flex:1
        }, {
            text: 'Created By',
            dataIndex: 'CreatedBy',
            flex: 1
        }],
        listeners:{
            select:'onGenreSelected_FORMA' //--> I'm thinking this will trigger                                 
                                          //-> a form (modal) containing the data to update
        }
    }]
});

A fiddle example would be great! Thank you!

Screenshot:

This is where I would like to display form modal that can sync/update my store when I modify some data.


Solution

  • To do store.sync() you need to set values on the record first.

    Example is without ViewModel: https://fiddle.sencha.com/#fiddle/3isg&view/editor

    select: function (grid, record) {
        console.log(record);
    
        let win = Ext.create("Ext.window.Window", {
            title: 'Edit',
            modal: true,
            autoShow: true,
            width: 400,
            height: 500,
            controller: {},
            items: [{
                xtype: 'form',
                reference: 'form',
                fieldLabel: 'name',
                items: [{
                    xtype: 'textfield',
                    name: 'name'
                }]
            }],
            buttons: [{
                text: 'cancel',
                handler: function () {
                    win.close();
                }
            }, {
                text: 'save',
                handler: function () {
                    var values = this.lookupController().lookup('form').getValues();
                    record.set(values);
                    grid.getStore().sync({
                        scope: this,
                        success: function () {
                            win.close();
                            Ext.toast({
                                html: 'Well done',
                                align: 't'
                            });
                        },
                        failure: function () {
                            Ext.toast({
                                html: 'Problem occurred',
                                align: 't'
                            });
                        }
                    });
    
                }
            }],
            listeners: {
                afterrender: function () {
                    this.lookupController().lookup('form').loadRecord(record);
                }
            }
        })
    }