I have a WinJS Repeater which is using a template. That template contains a WinJS list view. I can't seem to figure out how to use data-win-bind to set the inner list views itemDataSource.
My Repeater:
<section id="genreView" aria-label="Main content" role="main">
<div id="genreWrapper">
<div id="genreRows" data-win-control="WinJS.UI.Repeater"
data-win-options="{template: select('#genreRowTemplate')}">
</div>
</div>
</section>
My Template which contains a List View:
<div id="genreRowTemplate" data-win-control="WinJS.Binding.Template">
<div id="genreRow">
<h2 class="genreTitle" data-win-bind="innerText: genreTitle"></h2>
<div class="genreMovieListView"
data-win-control="WinJS.UI.ListView"
data-win-bind="itemDataSource : data"
data-win-options="{ layout: { type: WinJS.UI.GridLayout },
itemsDraggable: false,
selectionMode: 'single',
tapBehavior: 'none',
swipeBehavior: 'none',
itemsReorderable: false,
itemTemplate: select('#genreMovieTemplate')}">
</div>
</div>
</div>
My List View's template:
<div id="genreMovieTemplate" data-win-control="WinJS.Binding.Template">
<div class="genreMovieItem">
<img style="width: 175px; height: 250px;" data-win-bind="alt: title; src: posterUrl" />
</div>
</div>
The data for the repeater is similar to this (only it's a binding list):
var repeaterData = [{genreTitle: "titleA", data: new WinJS.Binding.List() },
{genreTitle: "titleB", data: new WinJS.Binding.List() }
{genreTitle: "titleC", data: new WinJS.Binding.List() }
{genreTitle: "titleD", data: new WinJS.Binding.List() }];
The data is created on the fly and each binding list is actually a lot more data so I can't get a good sample of real data.
What I DO get is a repeated control, repeated exactly the number of times as the records in my bound list. What I DON'T get is the binding list displayed. My inner binding list is not getting databound via the data-win-bind. I've tried a few things and I either get nothing or an error. Any help is appreciated. Thanks.
EDIT: I think the right way to bind would be data-win-bind="data-win-options.itemDataSource: data", but doing that throws the following confusing error: "JavaScript runtime error: WinJS.UI.Repeater.AsynchronousRender: Top level items must render synchronously".
I was able to solve my problem, but I don't think I went about it in the right way. I went ahead and set the data source for the repeater, which gives me my genreRows from above. This was always working, it was just the child dataSource I couldn't figure out how to get to. My solution... set it in code after it loads. Nothing fancy, just a solution that feels a bit hacky to me. Here's my code in case it helps someone else get past this problem.
var titleList = $(".genreRow > .genreTitle"); var genreLists = $(".genreRow > .genreMovieListView"); for (var i = 0; i < genreLists.length; i++) { var title = titleList[i].innerText; var listControl = genreLists[i].winControl; tempData.forEach(function (element, i) { if (element.genreTitle == title) listControl.itemDataSource = element.data.dataSource; }); };
Basically the above code assumes the title is unique (which it is). So it uses this as a key to traverse the data and set the itemDataSource that way.
I won't mark this as the accepted answer just in case someone can point out how to do this "right".