2

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.

1 Answers1

0

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);
            }
        }
    })
}
norbeq
  • 2,923
  • 1
  • 16
  • 20
  • Hi @norbeq , thank you very much! it's working now but I have some concerns that you may know, I printed the record to be edited and I noticed that it has an Id, when it hits my API, [httpPut] with my Dto as parameter, my dto is null and the data being sent was the id of the record, not the entire model. I resort to query string though just to fully update my record. Thanks again! I intentionally made this error just to see the url and the data being sent: https://pasteboard.co/oNwIRWtGBly5.png – Secundus Praxi Mar 08 '22 at 04:09
  • You can set `idProperty` in model to `genreId` so id will be taken from `genreId` instead of `id` which not exists – norbeq Mar 08 '22 at 14:12