Reputation: 26498
I am facing a problem. I am trying to bind a ListView WinJS control to a RESTful service that return a JSON object.
Here is my design (default.html)
<body>
<button id="btnExample">REST Service</button>
<div id="divDisplayItems" data-win-control="WinJS.Binding.Template">
<div>
<table border="1">
<tr>
<td><b>PersonId</b></td>
<td><b>PersonName</b></td>
</tr>
<tr>
<td><h4 data-win-bind="innerText: PersonId"></h4></td>
<td><h4 data-win-bind="innerText: PersonName"></h4></td>
</tr>
</table>
</div>
</div>
<div
id="basicListView"
style="width:250px;height:500px"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource :SourceData.itemList.dataSource, itemTemplate: select('#divDisplayItems'),layout : {type: WinJS.UI.ListLayout}}"
>
</div>
</body>
Here is my default.js code
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
WinJS.strictProcessing();
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
document.getElementById("btnExample").addEventListener("click", JSonRecord, false);
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
};
function JSonRecord(event) {
WinJS
.xhr(
{ url: "URL/EmployeeList" }
)
.then
(
function (response) {
var sourceData = JSON.parse(response.responseText);
var datalist = new WinJS.Binding.List(sourceData.EmployeeDetailsResult);
var dataMembers = { itemList: datalist };
WinJS.Namespace.define("SourceData", dataMembers);
}, function (error)
{
console.log(error);
}
);
}
app.start();
})();
Intension is that whenever the "btnExample" is cliekd, the ListView should be populated. The service is working fine and I am able to get proper data. But the moment I am trying to load the page, it is crashing.
If I comment
"data-win-options="{itemDataSource :SourceData.itemList.dataSource, itemTemplate: select('#divDisplayItems'),layout : {type: WinJS.UI.ListLayout}}"
the at least the page is loading.
What is the problem and how can I bind the data to the ListView Control ?
Thanks
Upvotes: 3
Views: 1284
Reputation: 4171
2 changes in Default.js
First Change
var app = WinJS.Application;
/* insert the line
WinJS.Namespace.define("SourceData",
{
itemList: new WinJS.Binding.List([])
})
*/
var activation = Windows.ApplicationModel.Activation;
Second Change
function (response)
{
var sourceData = JSON.parse(response.responseText);
var datalist = new WinJS.Binding.List(sourceData.EmployeeDetailsResult);
<-- basicListView is the Name of the div where you are binding the datasource -->
basicListView.winControl.itemDataSource = datalist.dataSource;
}
Watch this video for a better understanding.
Hope this helps
Upvotes: 1
Reputation: 4763
You're crashing because when you load the page and the ListView tries to bind, your list doesn't exist. It doesn't exist until after your asynchronous call to your web service. All you need to do to fix it is declare your WinJS.Binding.List earlier (perhaps just above your app.onactivated line next to the app alias). Then when you fetch your data, just iterate the results and push them into the already-existing List. Like this...
sourceData.EmployeeDetailsResult.forEach(function(r) {
yourList.push(r);
}
Upvotes: 2
Reputation: 5633
You are binding the ListView to the SourceData namespace which is not available until AFTER you click the button. Thus, you are trying to bind to a undefined value at runtime. You should set up the SourceData namespace at the top of your js file, prior to the activated event, and create it with an empty Binding List. Something like...
WinJS.Namespace.define("SourceData", {
itemList: new WinJS.Binding.List([]);
})
In your button click handle, you can just add the items to the existing list or create a new one and assign it from scratch.
There are some great tutorials that you can find at 30 Days, especially in Week 2 IIRC.
Upvotes: 2