PDA

View Full Version : refreshNode causes template's # (xindex) value to be set to 1



jep
17 Jun 2011, 10:32 AM
I've tested this both on 1.1.0 and on trunk as of today (2011-06-17). Both show a problem with this example:



<html>
<head>
<title>test</title>

<link rel="stylesheet" href="../sencha-touch-trunk/20110617/resources/css/sencha-touch.css" type="text/css">
<script type="text/javascript" src="../sencha-touch-trunk/20110617/sencha-touch-debug.js"></script>

<!-- <link rel="stylesheet" href="../sencha-touch-1.0.0/resources/css/sencha-touch.css" type="text/css">-->
<!-- <script type="text/javascript" src="../sencha-touch-1.0.0/sencha-touch-debug.js"></script> -->

<script type="text/javascript">

Ext.setup({
onReady: function() {
Ext.regModel('Contact', {
fields: ['firstName', 'lastName']
});

var list = new Ext.List({
itemTpl:'<div class="contact">{#} {name}</div>',
store: new Ext.data.Store({
model: 'Contact',
data: [
{name:'George'},
{name:'John'},
{name:'Thomas'},
]
})
});

var mainPnl = new Ext.Panel({
layout:'fit',
fullscreen: true,
items:list,
dockedItems:{
xtype:'toolbar',
dock:'top',
items:{xtype:'button', text:'Refresh', handler:function () { list.refreshNode(1) } }
}
});
}
});

</script>

</head>
<body></body>
</html>


When you click on the Refresh button, it calls refreshNode(1). You'll see that this causes that item to get its # template parameter value set to 1 instead of the correct value. Calling list.refresh() will cause it to be re-rendered with the correct value.

jep
21 Jun 2011, 8:34 AM
Well, this is a bit kludgy, but I have a workaround for it:



Ext.override(Ext.XTemplate, {
applyTemplate: function(values, xindex, xcount) {
//return this.master.compiled.call(this, values, {}, 1, 1);
return this.master.compiled.call(this, values, {}, xindex, xcount);
},

compileTpl: function(tpl) {
var fm = Ext.util.Format,
me = this,
useFormat = me.disableFormats !== true,
body, bodyReturn, evaluatedFn;

function fn(m, name, format, args, math) {
var v;
// name is what is inside the {}
// Name begins with xtpl, use a Sub Template
if (name.substr(0, 4) == 'xtpl') {
return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
}
// name = "." - Just use the values object.
if (name == '.') {
v = 'typeof values == "string" ? values : ""';
}

// name = "#" - Use the xindex
else if (name == '#') {
v = 'xindex';
}
else if (name.substr(0, 7) == "parent.") {
v = name;
}
// name has a . in it - Use object literal notation, starting from values
else if (name.indexOf('.') != -1) {
v = "values." + name;
}

// name is a property of values
else {
v = "values['" + name + "']";
}
if (math) {
v = '(' + v + math + ')';
}
if (format && useFormat) {
args = args ? ',' + args : "";
if (format.substr(0, 5) != "this.") {
format = "fm." + format + '(';
}
else {
format = 'this.' + format.substr(5) + '(';
}
}
else {
args = '';
format = "(" + v + " === undefined ? '' : ";
}
return "'," + format + v + args + "),'";
}

function codeFn(m, code) {
// Single quotes get escaped when the template is compiled, however we want to undo this when running code.
return "',(" + code.replace(me.compileARe, "'") + "),'";
}

bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
eval(body);

tpl.compiled = function(values, parent, xindex, xcount) {
var vs,
length,
buffer,
i;

if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
return '';
}

vs = tpl.target ? tpl.target.call(me, values, parent) : values;
if (!vs) {
return '';
}

parent = tpl.target ? values : parent;
if (tpl.target && Ext.isArray(vs)) {
buffer = [], length = vs.length;
if (tpl.exec) {
for (i = 0; i < length; i++) {
//buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent,
xindex == undefined ? i + 1 : xindex,
xcount == undefined ? length : xcount);
//tpl.exec.call(me, vs[i], parent, i + 1, length);
tpl.exec.call(me, vs[i], parent,
xindex == undefined ? i + 1 : xindex,
xcount == undefined ? length : xcount);
}
} else {
for (i = 0; i < length; i++) {
//buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent,
xindex == undefined ? i + 1 : xindex,
xcount == undefined ? length : xcount);
}
}
return buffer.join('');
}

if (tpl.exec) {
tpl.exec.call(me, vs, parent, xindex, xcount);
}
return evaluatedFn.call(me, vs, parent, xindex, xcount);
}

return this;
}
});

Ext.override(Ext.Template, {
overwrite: function(el, values, returnElement, xindex, xcount) {
el = Ext.getDom(el);
//el.innerHTML = this.applyTemplate(values);
el.innerHTML = this.applyTemplate(values, xindex, xcount);
return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
}
});

Ext.override(Ext.DataView, {
bufferRender : function(records, index){
var div = document.createElement('div');
//this.tpl.overwrite(div, this.collectData(records, index));
this.tpl.overwrite(div, this.collectData(records, index), undefined, index + 1, this.store.data.length);
return Ext.query(this.itemSelector, div);
}
});


From my limited tests, I haven't run into it causing any problems. But given what large amounts of code it replaces, I wouldn't be surprised if a minor release breaks it. Plus, this was based on the SVN version, so I'm not sure if it differs from the 1.1.0 release.