1. #1
    Sencha User
    Join Date
    Jul 2012
    Posts
    25
    Answers
    1
    Vote Rating
    1
    delebash is on a distinguished road

      0  

    Default Unanswered: Help getting associated data working in Etjs 4.2 MVC

    Unanswered: Help getting associated data working in Etjs 4.2 MVC


    Scenerio,

    Grid view that displays nested data. Not sure of the correct way to get this working in 4.2. I have it working by adding my nested field into the parent model. Parent model is Contact associated is ContactType, if I add ContactType.name to fields in Contact and add ContactType.name to grid, then nested data is displayed.

    1) Is this the proper way to show nested data in a grid or should it be done via association?

    2) Edit view popup load combobox with ContactTypes, this is working, but need to set selected value via the nested value ContactTypes from grid record

    3)Save data back to server, both primary Contact and associated ContactType. When saving I am trying to use record.getAssociatedData() in my writer getRecordData function but no associated data is available, so I am not sure how I am setting up my associations wrong?

    Grid is working, displaying nested data is working, loading combobox is working. Setting selected value not sure how. Setting up association so I can get all data to send back to server not working.

    Here is my code that I am trying

    Contacts Controller
    Code:
    Ext.define('SimplyFundraising.controller.Contacts', {
        extend: 'Ext.app.Controller',
    
    
        views: ['contacts.List', 'contacts.Edit'],
        init: function () {
            this.control({
                'contactslist': {
                    itemdblclick: this.editContact,
                    removeitem: this.removeContact
                },
                'contactslist > toolbar > button[action=create]': {
                    click: this.onCreateContact
                },
                // 'contactsadd button[action=save]': {
                // click: this.doCreateContact
                // },
                'contactsedit button[action=save]': {
                    click: this.updateContact
                }
            });
        },
        list: function () {
    
            var mystore = this.getStore('Contacts')
            mystore.proxy.extraParams = { $expand: 'ContactType'};
            mystore.load({
                params: {
                },
                callback: function(r,options,success) {
               //     debugger;
                } //callback
            }); //store.load
    // mystore.proxy.extraParams = { $expand: 'ContactType'};
    //        var User = this.getContactModel();
    //        User.load(258, {
    //            success: function (user) {
    //                console.log("Loaded user 258: " + user.get('lastName'));
    //            }
    //        });
        },
        editContact: function (grid, record) {
            var store = this.getStore('ContactTypes');
            store.load({
                params: {
                },
                callback: function(r,options,success) {
            //    debugger;
                } //callback
            }); //store.load
    
            var view = Ext.widget('contactsedit');
            view.down('form').loadRecord(record);
            this.addnew = false
        },
        removeContact: function (Contact) {
            Ext.Msg.confirm('Remove Contact ' + Contact.data.lastName, 'Are you sure?', function (button) {
                if (button == 'yes') {
                    this.getContactsStore().remove(Contact);
                }
            }, this);
        },
        onCreateContact: function () {
            var view = Ext.widget('contactsedit');
            this.addnew = true
        },
        // doCreateContact: function (button) {
        // var win = button.up('window'),
        // form = win.down('form'),
        // values = form.getValues(),
        // store = this.getContactsStore();
        // if (form.getForm().isValid()) {
        // store.add(values);
        // win.close();
        // }
        // },
        updateContact: function (button) {
            var win = button.up('window'),
                form = win.down('form'),
                record = form.getRecord(),
                values = form.getValues(),
                store =  this.getStore('Contacts')
            if (form.getForm().isValid()) {
                if (this.addnew == true) {
                    store.add(values);
                } else {
                    record.set(values);
                }
                store.sync();
                win.close();
            }
        }
    });
    Contact Model
    Code:
    Ext.define('SimplyFundraising.model.Contact', {
        extend : 'Wakanda.model',
        fields: ['firstName', 'middleName','lastName'],
        associations: [{
            type: 'hasOne',
            model: 'SimplyFundraising.model.ContactType',
            name: 'contacttypes',
            associationKey: 'ContactType',
            reader: {
                type: 'json',
                record: 'ContactType',
                idProperty: '__KEY',
                root: '__ENTITIES'
            }}
        ]
    
    
        associations: [{ type: 'hasOne', name: 'contacttype', model: 'SimplyFundraising.model.ContactType',associationKey: 'ContactType' }]
    });
    In contact model I have tried not specifying reader or root as in the examples and tried type as memory and json. Since my Contact model should already inherit the root property not sure if I need to respecify a reader again, either way it isnt working.

    ContactType model
    Code:
    Ext.define('SimplyFundraising.model.ContactType', {
        extend : 'Wakanda.model',
        fields: ['name',]
    });
    ContactsStore
    Code:
    Ext.define('SimplyFundraising.store.Contacts', {
        extend: 'Ext.data.Store',
        model: 'SimplyFundraising.model.Contact',
        autoLoad: false,
        autoSync: false
    
    
    });
    ContactTypesStore
    Code:
    Ext.define('SimplyFundraising.store.ContactTypes', {
        extend: 'Ext.data.Store',
        model: 'SimplyFundraising.model.ContactType',
        autoLoad: false,
        autoSync: false
    
    });
    Contact list view
    Code:
    Ext.define('SimplyFundraising.view.contacts.List', {
        extend : 'Ext.grid.Panel',
        xtype : 'contactslist',
        title : 'All Contacts',
        store : 'Contacts',
        autoHeight: true,
        autoScroll : true,
        viewConfig : {
            loadMask : true
        },
        initComponent : function() {
            this.tbar = [{
                text : 'Create Contact',
                action : 'create'
            }];
            this.columns = [{
                header : 'Id',
                dataIndex : '__KEY',
                width : 50
            }, {
                header : 'First Name',
                dataIndex : 'firstName',
                flex : 1
            }, {
                header : 'Middle Name',
                dataIndex : 'middleName',
                flex : 1
            }, {
                header : 'Last Name',
                dataIndex : 'lastName',
                flex : 1
            },
            {
                header : 'Type',
                dataIndex : 'ContactType.name',
                flex : 1
            }];
            this.addEvents('removeitem');
            this.actions = {
                removeitem : Ext.create('Ext.Action', {
                    text : 'Remove Contact',
                    handler : function() {
                        this.fireEvent('removeitem', this.getSelected())
                    },
                    scope : this
                })
            };
            var contextMenu = Ext.create('Ext.menu.Menu', {
                items : [this.actions.removeitem]
            });
            this.on({
                itemcontextmenu : function(view, rec, node, index, e) {
                    e.stopEvent();
                    contextMenu.showAt(e.getXY());
                    return false;
                }
            });
            this.callParent(arguments);
        },
        getSelected : function() {
            var sm = this.getSelectionModel();
            var rs = sm.getSelection();
            if (rs.length) {
                return rs[0];
            }
            return null;
        }
    });
    Contact edit view
    Code:
    Ext.define('SimplyFundraising.view.contacts.Edit', {
        extend: 'Ext.window.Window',
        xtype: 'contactsedit',
        title: 'Edit Contacts',
        layout: 'fit',
        stores: ['ContactTypes','Contacts'],
        autoShow: true,
        initComponent: function () {
            this.items = [
                {
                    xtype: 'form',
                    bodyStyle: {
                        background: 'none',
                        padding: '10px',
                        border: '0'
                    },
                    items: [
                        {
                            xtype: 'textfield',
                            name: 'firstName',
                            allowBlank: false,
                            fieldLabel: 'Name'
                        },
                        {
                            xtype: 'textfield',
                            name: 'lastName',
                            allowBlank: false,
                            fieldLabel: 'Last Name'
                        },
                        {
                            xtype: 'combobox',
                            fieldLabel: 'Contact Type',
    
                            store: 'ContactTypes',
    
                            displayField: 'name',
                            valueField: '__KEY',
                            typeAhead: true,
                            queryMode: 'local',
                            emptyText: 'Select a type...'
                        }
                    ]
                }
            ];
            this.buttons = [
                {
                    text: 'Save',
                    action: 'save'
                },
                {
                    text: 'Cancel',
                    scope: this,
                    handler: this.close
                }
            ];
            this.callParent(arguments);
        }
    });
    Code that my model,proxy,reader,writer inherit used to get data in correct format to and from server

    Wakanda Model
    Code:
    Ext.define('Wakanda.model', {
        requires: ['Wakanda.proxy'],
        extend: 'Ext.data.Model',
        fields: ['__KEY',{name: '__STAMP',persist: false}],
        idProperty: '__KEY',
    
        stampProperty: '__STAMP',
    
        proxy: 'wakanda',
    //    constructor: function () {
    //        this.callParent(arguments)
    //        return this;
    //    },
        onClassExtended: function (cls, data) {
            //    debugger;
            // cls.apply(this)
    //        var parts = data.$className.split('.');
    //        var entity = parts[2]
    //        var catalog = this.prototype.getCatalog(entity),
    //            attributes = catalog.attributes;
    //        for (var i = 0, l = attributes.length; i < l; i++) {
    //            if (attributes[i].name === 'ID') {
    //                attributes[i].persist = false;
    //            }
    //        }
    //        attributes.push({name: this.prototype.idProperty});
    //        attributes.push({name: this.prototype.stampProperty});
    //       // data.fields = attributes;
    //      //  debugger;
    //        //this.setFields(data.fields)
    //      // var mymodel = Ext.ModelManager.getModel(data.$className);
            //   debugger;
            // Ext.appy(this);
    //        //this.superclass.superclass.$onExtended.apply(this, arguments);
            // this.triggerExtended.apply(this,arguments)
            // cls.apply(this,arguments)
        },
    
        getCatalog: function (className) {
            var catalog;
            Ext.Ajax.request({
                async: false,
                url: 'http://127.0.0.1:8081/cors/$catalog/' + className,
                success: function (response) {
                    catalog = Ext.decode(response.responseText);
                }
            });
            return catalog;
        }
    
    });
    Wakanda proxy
    Code:
    Ext.define('Wakanda.proxy', {
        requires: ['Wakanda.reader', 'Wakanda.writer'],
        extend: 'Ext.data.proxy.Rest',
    
        // alternateClassName: 'SimplyFundraising.data.WakandaProxy',
    
        alias: 'proxy.wakanda',
    
        sortParam: '$orderby',
    
        filterParam: '$filter',
    
        startParam: '$skip',
    
        groupParam: '$group',
    
        limitParam: '$top',
    
        //  groupersParam: '$group',
    
        reader: 'wakanda',
    
        writer: 'wakanda',
    
        actionMethods: {
            create: 'POST',
            read: 'GET',
            update: 'POST',
            destroy: 'POST'
        },
    
        buildUrl: function (request) {
            //   debugger;
            // var modelName = this.model.modelName,
            var parts = this.model.modelName.split('.');
            var modelName = parts[2]
    
            operation = request.operation,
                records = operation.records || [],
                record = records[0],
                id = record ? record.getId() : operation.id,
                url = 'http://127.0.0.1:8081/cors/' + modelName,
                action = request.action;
    
            if (this.appendId && id && (action === 'read' || action === 'destroy')) {
                url += '(' + id + ')';
            }
    
            request.url = url;
    
            // console.log("buildUrl", this, arguments, request.url);
    
    
            if (action !== 'read') {
                if (action === 'create') action = 'update';
                else if (action === 'destroy') action = 'delete';
                url = Ext.urlAppend(url, '$method=' + action);
            }
    
            if (this.noCache) {
                url = Ext.urlAppend(url, Ext.String.format("{0}={1}", this.cacheString, Ext.Date.now()));
            }
    
            return url;
        },
    
        encodeSorters: function (sorters) {
            var min = [],
                length = sorters.length,
                i = 0, sort = '';
    
            for (; i < length; i++) {
                sort += sorters[i].property + ' ' + sorters[i].direction + ' ';
            }
    
            return sort;
        },
    
        encodeFilters: function (filters) {
            var min = [],
                length = filters.length,
                i = 0, filter = '';
    
            for (; i < length; i++) {
                filter += filters[i].property + ' eq ' + filters[i].value + '@ ';
            }
            return filter;
        }
    
    });
    Wakanda reader
    Code:
    Ext.define('Wakanda.reader', {
    
        extend: 'Ext.data.reader.Json',
    
        //alternateClassName: 'SimplyFundraising.data.WakandaReader',
    
        alias: 'reader.wakanda',
    
        root: '__ENTITIES',
    
        totalProperty: '__COUNT',
    
        getData: function (data) {
            //  debugger;
            if (Ext.isObject(data) && !data[this.root]) {
                data = [data];
            }
            return data;
        }
    
    });
    Wakanda writer
    Code:
    Ext.define('Wakanda.writer', {
    
        extend: 'Ext.data.writer.Json',
    
       // alternateClassName: 'SimplyFundraising.data.WakandaWriter',
    
        alias: 'writer.wakanda',
    
        writeAllFields: false,
    
        getRecordData: function(record,operation) {
            debugger;
            Ext.apply(record.data,record.getAssociatedData());
            debugger;
            var isPhantom = record.phantom === true,
                writeAll = this.writeAllFields || isPhantom,
                nameProperty = this.nameProperty,
                fields = record.fields,
                data = {},
                changes,
                name,
                field,
                key;
    
            if (writeAll) {
                // console.log("getRecordData1", this, arguments);
                fields.each(function(field){
                    if (field.persist) {
                        debugger;
                        name = field[nameProperty] || field.name;
                        data[name] = record.get(field.name);
                    } else {
    
                    }
    
                });
            } else {
                changes = record.getChanges();
                debugger;
                // console.log("getRecordData2", this, arguments, changes);
                for (key in changes) {
                    if (changes.hasOwnProperty(key)) {
                        field = fields.get(key);
                        name = field[nameProperty] || field.name;
                        data[name] = changes[key];
                    }
                }
                if (!isPhantom) {
                    debugger;
    
                    data[record.idProperty] = record.getId();
                    if(operation.action !== 'destroy'){
                    data[record.stampProperty] = record.get(record.stampProperty);
                    }
                }
            }
            return {'__ENTITIES': [data]};
        }
    
    });
    Sample json data for loading grid
    {
    Code:
       "__entityModel":"Contact",
       "__COUNT":21,
       "__SENT":21,
       "__FIRST":0,
       "__ENTITIES":[
          {
             "__KEY":"289",
             "__STAMP":11,
             "ID":289,
             "firstName":"a",
             "middleName":"",
             "lastName":"ffddgddf",
             "ContactType":{
                "__KEY":"2",
                "__STAMP":4,
                "ID":2,
                "name":"Home",
                "contactCollection":{
                   "__deferred":{
                      "uri":"/cors/ContactType(2)/contactCollection?$expand=contactCollection"
                   }
                }
             },
             "addressCollection":{
                "__deferred":{
                   "uri":"/cors/Contact(289)/addressCollection?$expand=addressCollection"
                }
             }
          },
          {
             "__KEY":"267",
             "__STAMP":5,
             "ID":267,
             "firstName":"a",
             "middleName":"",
             "lastName":"g",
             "ContactType":null,
             "addressCollection":{
                "__deferred":{
                   "uri":"/cors/Contact(267)/addressCollection?$expand=addressCollection"
                }
             }
          }
       ]
    }
    Thanks for any help,
    Dan
    Last edited by delebash; 13 May 2013 at 4:44 AM. Reason: addd aditional info for clarity

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    35,724
    Answers
    3359
    Vote Rating
    752
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      -1  

    Default


    First, let's start small. You have 1 model Contact that hasOne ContactType model. What does your data look like and are you loading the data for the association all in one?
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha User
    Join Date
    Jul 2012
    Posts
    25
    Answers
    1
    Vote Rating
    1
    delebash is on a distinguished road

      0  

    Default


    Thanks for the reply. Yes I have Contact model with hasOne ContactType

    I am getting data all in one, Contact with nested ContactType

    Data

    Code:
    {
       "__ENTITIES":[
          {
             "__KEY":"289",
             "__STAMP":20,
             "ID":289,
             "firstName":"a",
             "middleName":"",
             "lastName":"a",
             "ContactType":{
                "__KEY":"2",
                "__STAMP":4,
                "ID":2,
                "name":"Home"
             }
          }
       ]
    }
    1) Showing the data in the grid.
    I can add ContactType.name to Contact model and as a field in the grid and the grid displays the ContactType, however since I have an association to ContactType I would think that I would not have to add ContactType to my Contact model.

    So I tried using the render function for the ContactType field in the gird like so
    Code:
    {
                header : 'Contact Type',
                renderer: function (val, meta, record) {
                    return record.getContactType().get('name')
                }
    }
    getContactType() is the getter for the ContactType association. The above code also works, but it also makes a remote call to the server, which is not needed since I already have the data loaded. I tested in the debugger and just ran record.getContactType().get('name') and the correct associated data is returned without making a remote call to the database, not sure why this same code when placed in the render function of a grid field decides to make the remote call.

    Then the remaining issues with combobox and sending data back to server, but as you suggested lets start small.

    Thanks again very much for your help, I am trying the best I can to understand proper way to make this work

    If you think it would help I can put the app up on the web for you to look at so you can the full picture easier.
    Last edited by delebash; 16 May 2013 at 5:25 PM. Reason: spellling

Thread Participants: 1

Tags for this Thread

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar