1. #1
    Sencha User
    Join Date
    Nov 2012
    Posts
    19
    Vote Rating
    0
    bothwell is on a distinguished road

      0  

    Default Answered: What is the correct syntax for displaying data set with setData in a view?

    Answered: What is the correct syntax for displaying data set with setData in a view?


    Having trouble getting the output in a tpl working.

    Controller:
    Code:
            // look up the contact by their ID
            var contactsStore = Ext.getStore("Contacts"); 
            contactsStore.load();
            var record = contactsStore.getById(record);
            
            // load the contact's data into the panel 
            var contactDetailView = this.getContactDetailView();
            contactDetailView.setData(record.data);
            Ext.Viewport.animateActiveItem(contactDetailView, this.slideLeftTransition);
    View:
    Code:
                {
                    xtype: "panel",
                    styleHtmlContent: true,
                    tpl: '<div class="lsks">{_data.firstname} {lastname} - {data.email}</div>',
                }
    (none of the syntaxes I've used above work - the page is just blank, no data)

    Also in the same view as a test:
    Code:
        onSaveContactButtonTap: function () {
            console.log(this.getData()); // this outputs the correct data record object to the console
            console.log(this._data); // this also outputs the correct data record object to the console
            console.log(this.data); // this outputs 'undefined'
        }
    As I understand it I should be able to use this.data to output the contents of the data array, but that's not working for me. The data is obviously getting through, as evidenced by this.getData(). Is the problem in the tpl due to this.data being undefined? If so, how do I get this.data to be defined? Or is there something else I'm missing?

    Thanks for any help.

  2. Code:
    {
        xtype: "panel",
        styleHtmlContent: true,
        tpl: '<div>{firstname}</div>',//<--your field name is firstname
        data:'',
        listeners: {
            painted: function(componentItSelf) {
                console.log(componentItSelf.getData());
                //var myvar = data.parent.data; 
            }
        }
    }
    Code:
    //second argument is not a record  
    activateContactDetailView: function(view, recordIndex, item, index, e) {
        // var everything at first
        var contactsStore = Ext.getStore("Contacts");
        var contactDetailView = this.getContactDetailView(),
        var record;
        contactsStore.load(function(){
               //load is async,write your logic in callback
              record= contactsStore.getById(recordIndex + 1);
              //not the contactDetailView,it should be contactDetailView's items[1],its xtype is panel
              contactDetailView.down('panel').setData(record.data);
              // record.data is private,you'd better use contactDetailView.down('panel').setRecord(record);
        });
        Ext.Viewport.animateActiveItem(contactDetailView, this.slideLeftTransition);
    }

  3. #2
    Sencha User
    Join Date
    Nov 2012
    Posts
    19
    Vote Rating
    0
    bothwell is on a distinguished road

      0  

    Default


    I've tried using a dataview, viz:

    Code:
                {
                    xtype: "dataview",
                    emptyText: "Nothing to display",
                    store: "Contacts",
                    itemTpl: [
                              '<div class="myrecord">',
                              '{firstname}',
                              '</div>'
                          ].join('')
                }
    Using the dataview, I get a list of firstnames. I don't want a list of names as this is a detail view, so this is just a test to see if I can get something to render. The original panel:

    Code:
                {
                    xtype: "panel",
                    styleHtmlContent: true,
                    tpl: '<div class="lsks">{_data.firstname} {firstname} {data.firstname}</div>',
                }
    still displays nothing for any of those attempts at rendering content.

    I'm obviously doing something wrong, but I'm beating my head on the wall trying to figure out what. A possibility I've thought of is that the view is being added to the viewport before the detail data has loaded, which would make sense as the detail data is only retrieved when you click through from another view.

    If this is the case, how do I update the view with the new data that's being passed in? Everything I can find on the net seems to describe using DataViews instead but as I only want one record at a time it doesn't seem appropriate.

  4. #3
    Sencha User
    Join Date
    Nov 2012
    Posts
    19
    Vote Rating
    0
    bothwell is on a distinguished road

      0  

    Default


    I'm still not having any luck with this.

    Assuming that the information needed to updated on show, I added a show function to my detail view:

    Code:
        show: function(){
            this.data = this.getData();
            console.log(this.data);
            this.callParent();
        }
    The assignment of this.data is needed because otherwise this.data is undefined. But assigning this.data some data on show doesn't actually populate the view with the data. In the item tpl that I'm trying to populate I added a painted listener to see if the data still exists:

    Code:
                {
                    xtype: "panel",
                    styleHtmlContent: true,
                    tpl: '<div class="lsks">{_data.firstname} {data} {data.firstname} {firstname} </div>',
                    listeners: {
                        painted: function(data) { 
                            console.log(this.getData()); 
                        }
                    }
                }
    this.getData() inside the painted listener returns null.

    Why can I not set the data inside the view?

  5. #4
    Sencha User bricemason's Avatar
    Join Date
    Jan 2008
    Location
    Upstate NY
    Posts
    280
    Vote Rating
    44
    Answers
    49
    bricemason has a spectacular aura about bricemason has a spectacular aura about bricemason has a spectacular aura about

      0  

    Default


    Here is an example to get your sanity back. It's a panel with children consisting of a panel that has a template defined and data configured for it and a button used to set new data.

    Code:
    {
        items: [
            {
                id: 'inlineDataPanel',
                tpl: 'First Name: {firstName}, Last Name: {lastName}',
                data: {
                    firstName: 'Sammy',
                    lastName: 'Hamm'
                }
            },
            {
                xtype: 'button',
                text: 'set new data',
                handler: function(btn) {
                    Ext.getCmp('inlineDataPanel').setData({
                        firstName: 'Nigel',
                        lastName: 'Bitters'
                    });
                }
            }
        ]
    }
    Once you can confirm that it works for you, it's important for us to understand what you want to accomplish. How does your app arrive at the detail view? What are you using as the list? What does your Contacts model look like? What does that whole controller code look like? Do you have a snippet of json that should be populating your store?

    I think your most likely problem is that the data is not loaded before you're attempting to work with it. More and clearer details are necessary though for us to help you. Post a more cohesive code sample and description of what you're truly trying to accomplish.

    Brice
    Brice Mason
    Front End Developer
    Modus Create

    @bricemason
    bricemason.com

    Sencha Touch Screencasts
    Vimeo - Sencha Touch Channel

    Github Projects:
    Sencha Cordova Builder enables the automatic creation, building, and running of PhoneGap (Cordova) projects with Sencha Touch.

    Am I Sencha Touch Ready? checks your system to determine what you need to do to start Sencha Touch development. If you're having trouble getting up and running, try this out.

    Sencha Tools Bridge allows Sencha SDK Tools to co-exist with Sencha Cmd on the same system.

  6. #5
    Sencha User
    Join Date
    Nov 2012
    Posts
    19
    Vote Rating
    0
    bothwell is on a distinguished road

      0  

    Default


    Hi Brice - thanks for the help! At this stage I realise the question is becoming more and more confused, which is a reflection of how muddled it is in my head. Your sample does work as intended.

    I'll try to straighten it out and describe the surrounding architecture more fully.

    The model looks like this:
    Code:
    Ext.define("EnablerApp.model.Contact", {
        extend: "Ext.data.Model",
        config: {
            identifier: 'uuid',
            idProperty: 'auto',
            fields: [
                { name: 'enablerid', type: 'int' },
                { name: 'email', type: 'string' },
                { name: 'firstname', type: 'string' },
                { name: 'lastname', type: 'string' },
                { name: 'company', type: 'string' },
                { name: 'jobtitle', type: 'string' },
                { name: 'phone', type: 'string' },
                { name: 'mobile', type: 'string' },
                { name: 'address', type: 'string' },
                { name: 'postcode', type: 'string' }
            ],
            validations: [
                { type: 'presence', field: 'enablerid' },
                { type: 'presence', field: 'firstname', message: 'Please enter a first name for this contact.' },
                { type: 'presence', field: 'lastname', message: 'Please enter a last name for this contact.' },
                { type: 'presence', field: 'email', message: 'Please enter an email address for this contact.' }
            ]
        }
    });
    app.js (only the main Contacts list is loaded at this stage)
    Code:
    Ext.application({
        name: "EnablerApp",
        useLoadMask: true,
        
        models: ['Setting','Contact'],
        stores: ['Settings','Contacts'],
        controllers: ['Toolbar','Settings','Contacts'],
        views: ['ReportsList','ContactsList','SettingsList','Toolbar'],
        
        
        launch: function(){
            var ReportsList = {
                xtype: "reportslistview"
            };
            
            var ContactsList = {
                xtype: "contactslistview"
            };
            var SettingsList = {
                xtype: "settingslistview"
            };
    
            Ext.Viewport.add([ReportsList,ContactsList,SettingsList]);
        }
    });
    The contacts controller then loads in its own sub-views and does synchronisation and deciding what to display:
    Code:
    Ext.define("EnablerApp.controller.Contacts", {
        extend: "Ext.app.Controller",
        requires: [
            "EnablerApp.view.ContactDetail",
        ],
        config: {
            refs: {
                contactsList: "contactslistview",
                contactDetailView: "contactdetailview"
            },
            control: {
                contactsList: {
                    viewContact: "onViewContact"
                },
                contactDetailView: {
                    backToContactsList: "onbackToContactsList"
                }
            }
        },
        
        doSync: function(contacts){
    // omitted for brevity - this function syncs the results of a JSON request to a remote server into local storage, currently works correctly
        },
    
        /** View an individual contact's details. **/
        onViewContact: function(params) {
            var self = this;
            
            // get an individual's contact details
    var oPacket = 'contains an authentication string and contact id number for a remote API';
    
            Ext.Ajax.request({
                url: 'http://api-service',
                params: {"EnablerCommand":oPacket},
                success: function(response){               
                    var text = Ext.JSON.decode(response.responseText);
                    if(text.status){
                        if (text.status.code == 0) {
                            var contactsStore = Ext.getStore("Contacts");
                            contactsStore.load();
    
    
    // the result from the API is then sent to local storage (I have verified this works correctly)
                            self.doSync('individual', text.contact.data);
    
    // I then send the user to the detailed view for this contact, passing the local storage record number as a parameter
                            self.activateContactDetailView('contactdetailview', contactsStore.find('enablerid',text.contact.data.id));
                        }
                    }
                },
                failure : function(response) {
                     Ext.Msg.alert('Error','Error while communicating with the remote server.');
                }
            }); 
        },
    
        activateContactDetailView: function (view, record, item, index, e) {
            // look up the contact by their ID
            var contactsStore = Ext.getStore("Contacts"); 
            contactsStore.load();
            
            // load the contact's data into the panel 
            var contactDetailView = this.getContactDetailView();
    
            // the record indexes that get passed in from the main list begin at 0 whereas the data store records begin at 1.
            var record = contactsStore.getById(record+1); 
            
            contactDetailView.setData(record.data);
    
            Ext.Viewport.animateActiveItem(contactDetailView, this.slideLeftTransition);
        },
        
        // Transitions
        slideLeftTransition: { type: 'slide', direction: 'left' },
        slideRightTransition: { type: 'slide', direction: 'right' },
        
        // Base Class functions.
        launch: function () {
            var contactDetailView = {
                xtype: "contactdetailview"
            };
    
            Ext.Viewport.add([contactDetailView]);
                
            this.callParent(arguments);
        }
    });
    And then in the detail view I've gone crazy (as you've noted!) trying to get the results of that setData call visible.
    Code:
    Ext.define("EnablerApp.view.ContactDetail", {
        extend: "Ext.form.Panel",
        requires: [
            "Ext.form.FieldSet",
            "Ext.form.Number"
        ],
        alias: "widget.contactdetailview",
        config: {
            id: 'viewContactDetail',
            layout: {
                type: 'fit'
            },
            items: [
                {
                    xtype: "toolbar",
                    docked: "top",
                    title: "Detail"
                },
                {
                    xtype: "panel",
                    styleHtmlContent: true,
                    tpl: '<div>{data.parent.data.firstname} {myvar.firstname} {this.data.firstname} {firstname} {data.firstname}</div>',
                    listeners: {
                        painted: function(data) {
                            console.log(data.parent.data);  // this outputs to the console the object that I want so I know the page has access to it somewhere - but only if I explicitly assign the contents of this.data in show: function() {}
                            var myvar = data.parent.data; 
                        }
                    }
                },
            ]
        },
        show: function(){
            this.data = this.getData(); // if i comment out this line, data.parent.data in the painted listener above is undefined
            this.callParent();
        }
    });
    I hope this makes a little more sense - I'm fairly new to ST2 and Extjs so am having difficulty with a lot of concepts including how to accurately frame the things I'm having trouble with.

  7. #6
    Sencha User
    Join Date
    Apr 2010
    Location
    China
    Posts
    227
    Vote Rating
    20
    Answers
    64
    haduki will become famous soon enough haduki will become famous soon enough

      0  

    Default


    Code:
    {
        xtype: "panel",
        styleHtmlContent: true,
        tpl: '<div>{firstname}</div>',//<--your field name is firstname
        data:'',
        listeners: {
            painted: function(componentItSelf) {
                console.log(componentItSelf.getData());
                //var myvar = data.parent.data; 
            }
        }
    }
    Code:
    //second argument is not a record  
    activateContactDetailView: function(view, recordIndex, item, index, e) {
        // var everything at first
        var contactsStore = Ext.getStore("Contacts");
        var contactDetailView = this.getContactDetailView(),
        var record;
        contactsStore.load(function(){
               //load is async,write your logic in callback
              record= contactsStore.getById(recordIndex + 1);
              //not the contactDetailView,it should be contactDetailView's items[1],its xtype is panel
              contactDetailView.down('panel').setData(record.data);
              // record.data is private,you'd better use contactDetailView.down('panel').setRecord(record);
        });
        Ext.Viewport.animateActiveItem(contactDetailView, this.slideLeftTransition);
    }
    I write English by translator.

  8. #7
    Sencha User
    Join Date
    Nov 2012
    Posts
    19
    Vote Rating
    0
    bothwell is on a distinguished road

      0  

    Default


    Haduki, thanks so much! Appreciate the extra comments to describe what's going on, I didn't realise load() was asynchronous and would probably never have understood the relationship between the view and its child panel from the controller on my own.

    Thanks again for your help, can definitely see light at the end of the tunnel now!

Thread Participants: 2

Tags for this Thread