PDA

View Full Version : XTemplate Problem & Solution



jwall
18 Oct 2010, 9:25 PM
On the API page for XTemplate, it explains that given a data structure that looks like:


var data = {
name: 'Tommy Maintz',
title: 'Lead Developer',
company: 'Ext JS, Inc',
email: 'tommy@extjs.com',
address: '5 Cups Drive',
city: 'Palo Alto',
state: 'CA',
zip: '44102',
drinks: ['Coffee', 'Soda', 'Water'],
kids: [{
name: 'Joshua',
age:3
},{
name: 'Matthew',
age:2
},{
name: 'Solomon',
age:0
}]
};

That the following XTemplate would work:


var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Title: {title}</p>',
'<p>Company: {company}</p>',
'<p>Kids: ',
'<tpl for="kids">', // interrogate the kids property within the data
'<p>{name}</p>',
'</tpl></p>'
);

I was attempting to implement code using XTemplates and a model I had defined. My model is defined like this:


Ext.regModel('GameState', {
fields: [
{
name: 'gametoken',
type: 'string'
},

{
name: 'username',
type: 'string'
},

{
name: 'usertoken',
type: 'string'
},

{
name: 'role',
type: 'string'
}
],

hasMany: {
model: 'AllPlayers',
name: 'players',
associationKey: 'players'
}
});

Ext.regModel('AllPlayers', {
fields: [
{
name: 'playername',
type: 'string'
},
{
name: 'isalive',
type: 'boolean',
defaultValue: true
},
{
name: 'isready',
type: 'boolean',
defaultValue: false
}
],
belongsTo: 'GameState'
});

And I had a template that looks like this:


new Ext.XTemplate(
'<tpl for="players">',
'<div class="players">',
'<div class="playername">{playername}</div>',
'<div class="playerready">{isready}</div>',
'</div>',
'</tpl>')

Because all I wanted was to output the players which exist in a GameState. Unfortunately I would always end up with a blank page, and in my browser's JavaScript console would be this error:

Uncaught ReferenceError: players is not defined

I checked a million different things, ensuring that a "GameState" Model instance was indeed in the Store that I bound to the Ext.DataView to which the above XTemplate was attached. In the end (after hours of debugging) I found that I had to create a template like this:


new Ext.XTemplate(
'<tpl for=".">',
'<tpl for="players">',
'<div class="players">',
'<div class="playername">{playername}</div>',
'<div class="playerready">{isready}</div>',
'</div>',
'</tpl>',
'</tpl>' )

Wrapping everything in an extra <tpl for="."></tpl> loop... something which was never explicitly shown in any example, nor was it obvious based on the example template in the XTemplate API document. Hopefully other people running into the same problem can use this information to fix it faster than I did :)

mrnap
20 Oct 2010, 10:57 PM
I seem to be having the same problem with xtemplates, but your solution doesn't work for me, I still get the Cant' find variable issue. Could it be the way I'm loading the proxy/reader?

Here are my models and my store/template loading code:



Ext.regModel('Date', {
fields: [
'id','date'
],

hasMany: {model: 'Timeslot', name: 'timeslots', associationKey: 'time'},

proxy: {
type: 'rest',
url: '../JSON/prodTest.JSON',
reader: {
type: 'json',
root: 'DAY'
}
}

});

Ext.regModel('Timeslot', {
fields: [
'id','timeslot','show'
],

hasMany: {model: 'Episode', name: 'episodes', associationKey: 'show'},
belongsTo: 'Date'
});

Ext.regModel('Episode', {
fields: [
'name','sid','network','title','ep','timeslot_id'
],

belongsTo: 'Timeslot'
});


and the view load:



var epList = new Ext.DataView({
store: new Ext.data.Store({
autoLoad: true,
model: 'Date'
}),
tpl: new Ext.XTemplate(
'<tpl for=".">' +
'<tpl for="time">' +
'<div>{timeslot}</div>' +
'</tpl>' +
'</tpl>'
),
fullscreen: true
});



I've also tried timeslot, timeslots, Timeslot for the tpl for= key, and none of those work either. Any ideas?

jwall
20 Oct 2010, 11:31 PM
Try setting your XTemplate up like this:



tpl: new Ext.XTemplate(
'<tpl for=".">',
'<tpl for="timeslots">',
'<div>{timeslot}</div>',
'</tpl>',
'</tpl>')



If that doesn't work, can you post a sample of the JSON data that is returned? Also, was your error exactly the same as the one I was getting?

mrnap
21 Oct 2010, 11:27 AM
That doesn't work, if you check out the end of my previous code you'll see the other keys I tried. I double checked the error, and it's not exactly the same, the one I'm getting says:

ReferenceError: Can't find variable: time

Here is a sample of my JSON, it's a lot longer usually and there are multiple dates but I just wanted to give you an idea of how shows: could be nested or have one member.



{
"DAY":
[
{
"date":"2010-10-19",
"time":
[
{
"timeslot":"09:00 am",
"show":
{
"name":"Live with Regis and Kelly",
"sid":"4263",
"network":"Syndicated",
"title":"Kristen Stewart, Jesse McCartney, Pee-Wee Herman",
"ep":"29x42",
"link":"http://test.com"
}
},
{
"timeslot":"10:00 am",
"show":
{
"name":"The Ellen DeGeneres Show",
"sid":"5750",
"network":"Syndicated",
"title":"Chris O'Donnell,
Ashley Tisdale",
"ep":"08x27",
"link":"http://test.com"
}
},
{
"timeslot":"08:00 pm",
"show":
[
{
"name":"America's Next Top Model",
"sid":"2589",
"network":"The CW",
"title":"Francesco Carrozzini",
"ep":"15x07",
"link":"http://test.com"
},
{
"name":"Survivor",
"sid":"5418",
"network":"CBS",
"title":"Worst Case Scenario",
"ep":"21x06",
"link":"http://test.com"
},
{
"name":"The Middle",
"sid":"20678",
"network":"ABC",
"title":"Foreign Exchange",
"ep":"02x05",
"link":"http://test.com"
},
{
"name":"Campus PD",
"sid":"24536",
"network":"G4",
"title":"Season 2,
Episode 8",
"ep":"02x08",
"link":"http://test.com"
},
{
"name":"Pair of Kings",
"sid":"24825",
"network":"Disney XD",
"title":"The Brady Hunch",
"ep":"01x06",
"link":"http://test.com"
},
{
"name":"Undercovers",
"sid":"24837",
"network":"NBC",
"title":"Not Without My Daughter",
"ep":"01x05",
"link":"http://test.com"
},
{
"name":"Dragon Ball Z Kai",
"sid":"25859",
"network":"NickToons",
"title":"Frieza Closes In! Mighty Porunga,
Grant Our Wish!",
"ep":"02x01",
"link":"http://test.com"
}
]
}
]
}
]
}


Is it possible that I need to put a wrapper div around the variables? I'm just kind of stuck, and there is no documentation that I could find about accessing nested models in templates.

jwall
21 Oct 2010, 8:28 PM
I would debug your JavaScript and make sure that the store actually contains models of the type your are expecting, and with all the data filled as expected.

Animal
21 Oct 2010, 9:09 PM
It's nothing to do with templates.

Your JSON is strange Reader ad Model definitions do not match it.

Is "show" an object or an Array? Where is the regular, repeating object which you are putting into a Model.

mrnap
22 Oct 2010, 10:52 AM
First off, thanks again for helping me with this, I really appreciate it.

Yah, sorry, I tried to grab a snippet to make it more readable. I'm pretty sure my JSON is good, here's a link to the full test data (http://bit.ly/9YHhaK) (it starts with DAY as the key and has an array of two date objects).

Shows can either be an array of shows or a singular object of one show, there is no way of telling which way ahead of time besides counting the members pre-load. I was under the impression that Sencha Touch could handle that difference on the fly, do I need to extend the store load?

JWall: I have debugged the code, I added a callback function to the store and was able to output every level of my store (JSON) to console.log(), including the shows when they were either array or object. Is there documentation somewhere out there that explains how you can basically remap JSON data to your ExtJS models so you can have more readable field? I thought that's what the 'name' option of hasMany does for the highest model level item.

Do you think having models setup like I do is the best way to access/store this 3 level deep nested data, or would you recommend something else? Also, the users who access this will only need to refresh this data once a day, is there a way you would recommend to store/access it that would possibly be faster than loading the store via proxy every time they load the page?