Reputation: 85
So I'm trying to display via a template some data from a JSON request. The data has some nested objects (of varying amounts) similar to this:
data: "Some data",
nested: [
{
nested_data: "foo",
bar: "foobar"
}, ...
],
...
I've managed to parse the JSON fine and store it in a WinJS.Binding.List
object, and bound the result to a template. The problem I've got is actually displaying the nested JSON data in my template. The template looks something like this:
<div class="appTemplate">
<div class="innerTemplate">
<h1 data-win-bind="innerText: data">
<h2 data-win-bind="innerText: nested">
</div>
</div>
When I run the program those, the 'nested' part of the template is just a bunch of [object Object]
rather than the data I want to display.
Is there some way I can create the template such that it can handle the nested data? Would it be easier to define a template function? Not sure what to do here...
Upvotes: 0
Views: 1152
Reputation: 369
This will be much easier with a template function.
The built in bindable templates are great for templates that are logicless, but fall short when you need the template to make decisions based on data values, and in your case, deeper properties.
Upvotes: 0
Reputation: 7292
There is no built in way to do this -- the only built in control for iterating over data is the List View. However, you cannot nest List Views.
There are two ways to solve this problem, depending on your desired outcome:
1) Stringifying the nested data: You can do this by writing a WinJS.Binding.converter
that will convert your array of data into a single string value. Example
Code:
WinJS.Namespace.define("Examples.Converters", {
nestedDataConverter: WinJS.Binding.converter(function(input) {
// Assume input is array
var result = "";
input.forEach(function(data) {
result += data.nested_data + ", " + bar + ";";
});
result result;
}),
});
Template:
My recommended solution would to build your own control that will take your array (or WinJS.Binding.List
) and create the elements / layouts needed. I have done this in a project I work on, and it's super simple.
Example Template:
<div class="appTemplate" data-win-control="WinJS.Binding.Template">
<div class="innerTemplate">
<h1 data-win-bind="innerText: data">
<h2 data-win-bind="innerText: nested Examples.Converters.nestedDataConverter">
</div>
</div>
Now, the h2 will have the single-string version of that data.
2) Create a control to display the data richly: To do this you need to create a new WinJS control and use it in your template.
Control example:
WinJS.Namespace.define("Examples.Controls", {
Stamper: WinJS.Class.define(function(element, options) {
WinJS.UI.setOptions(this, options);
this.domElement = element;
}, {
domElement: nullm
_data: null,
data: {
set: function(val) {
this._data = val;
updateLayout();
}
},
updateLayout: function() {
this.domElement.innerHTML = "";
if(!this._data) {
return;
}
this._data.forEach(function(item) {
var el = document.createElement("div");
el.textContent = "Data: " + item.nested_data + ", " + item.bar;
this.domElement.appendChild(el);
}.bind(this));
}
}),
});
Template:
<div class="appTemplate" data-win-control="WinJS.Binding.Template">
<div class="innerTemplate">
<h1 data-win-bind="innerText: data"></h1>
<div data-win-control="Examples.Controls.Stamper"
data-win-bind="winControl.data: nested"></div>
</div>
</div>
This control can be extended to render nested templates, and other items. It's all a question of how complex you want to get.
Upvotes: 4