There is a bug in WinJS that makes programmatically creating templates impossible. That is, the following code will never work:
WinJS.UI.setOptions(el.winControl, {
itemTemplate: new WinJS.Binding.Template(itemTemplateEl)
});
This code is attempting (!) to set a winControl's itemTemplate
property to a new WinJS.Binding.Template
object. But, it internally calls the setRenderer
method shown below (ui.js
). Which has a horrible, horrible bug.
This means programmatically setting templates is impossible with WinJS. A more extensive example of how this might occur in a very natural app is in complete-repo.html
.
As mentioned, the buggy code is shown below in ui.js
. The specific line in question is
this.renderer = newRenderer.renderItem;
This exhibits a classic JavaScript mistake, which you see repeatedly in StackOverflow questions: not differentiating between methods and functions. In short, the WinJS team is treating newRenderer.renderItem
as a function, when in fact it is a method. By simply assigning it, as you would a function, you lose an important piece of context: the this
pointer for the method.
The fix is to properly extract the method as a method, using Function.prototype.bind
:
this.renderer = newRenderer.renderItem.bind(newRenderer);
Fixing this would introduce no compatibility issues. There is a code path that currently never works, so nobody can possibly be using it. This change would make it work.
A runtime patch to fix this behavior is shown in fix.js
. As with all such runtime patches, the process is fragile.
Such a fundamental mistake in JavaScript semantics (the difference between methods and functions) does not inspire confidence. And the fact that it's in such a basic piece of the WinJS library (templating!) makes me concerned about the test coverage of the library in general.
This makes me fear that Microsoft does not expect us to write "real" WinJS apps, but only small, single-page samples that wouldn't need the flexibility provided by e.g. programmatic template binding.
@spankyj sorry if I jump in here, I have a template related problem. Although its a declarative template.
I have an img element with an onerror handler in the template that hides the element if an error occurs during the image load
<img src="#" data-win-bind="src:brandLogo" onerror="this.style.display='none'"/>
However, all img elements are hidden when one of the listviews items cannot load its image.
Any ideas?