Quickstart: Adding a ListView (HTML)
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
Most apps display lists of data, such as a list of contacts, images in a gallery, or the contents of an email inbox. These lists can obtain their data from a database, the web, or a JSON data source. Windows Library for JavaScript provides a ListView control that you can use to display data.
Prerequisites
You should be able to create a basic Windows Runtime app using JavaScript that uses WinJS controls. For instructions on getting started with WinJS controls, see the Quickstart: adding WinJS controls and styles.
What is a ListView?
The ListView is a WinJS control that displays data from an IListDataSource in a customizable list or grid. The WinJS provides several types of IListDataSource objects:
- You can use a List to create an IListDataSource from an array of data.
- You can use a StorageDataSource to access info about files and directories.
You can also create your own custom data source that connects to some other type of data provider, such as a web service or database. For instructions, see How to create a custom data source.
Creating a ListView
To create a ListView
Add references to the WinJS to your HTML file if they aren't already there.
To use the latest version of WinJS:
- Download the latest version from Get WinJS and copy it to the directory for your app or website.
- Add WinJS CSS and script references to each page of your app or website that uses WinJS features.
<!-- WinJS references --> <link href="/WinJS/css/ui-dark.css" rel="stylesheet"> <script src="/WinJS/js/WinJS.js"></script>
This example shows the HTML for the default.html file that is generated when you create a new Blank App project in Microsoft Visual Studio.
<!-- default.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ListViewExample</title> <!-- WinJS references --> <link href="/WinJS/css/ui-dark.css" rel="stylesheet"> <script src="/WinJS/js/WinJS.js"></script> <!-- ListViewExample references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> </head> <body> <p>Content goes here</p> </body> </html>
In your HTML file, create a div element and set its data-win-control property to
WinJS.UI.ListView
.<div id="basicListView" data-win-control="WinJS.UI.ListView"> </div>
In the JavaScript code that accompanies your HTML file, call the WinJS.UI.processAll function when your HTML is loaded.
WinJS.UI.processAll();
The next example shows the default.js file that accompanies the default.html file created for you when you create a new Blank Application project.
(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()); } }; 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(). }; app.start(); })();
This example works if you're adding the ListView to your start page (default.html). If you're adding the ListView to a Page control, you don't need to call WinJS.UI.processAll because the Page control does it for you. If you're adding the ListView to your own custom HTML, you can use the DOMContentLoaded event to call WinJS.UI.processAll. For more info about activating your controls, see Quickstart: Adding WinJS controls and styles.
This code creates an empty ListView. If you run the app, you won't see anything yet. In the next section, you create some data for the ListView to display.
Defining your data
Putting the code to create your data source in a separate JavaScript file can make it easier to maintain. In this section, you learn how to create a JavaScript file for your data, how to create a List, and how to use the WinJS.Namespace.define function to make the data accessible to the rest of your app.
Use Visual Studio to add a data file to your project. In the Solution Explorer, right click your project's
js
folder and select Add > New Item. The Add New Item dialog appears.Select JavaScript File. Give it the name "dataExample.js". Click Add to create the file. Visual Studio creates a blank JavaScript file named dataExample.js.
Open dataExample.js. Create an anonymous function and turn on strict mode.
As described in Coding basic apps, it's a good programming practice to encapsulate your JavaScript code by wrapping it in an anonymous function, and it's a good idea to use strict mode.
(function () { "use strict"; })();
Create an array of data. This example creates an array of objects. Each object has three properties: title, text, and image.
(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; })();
Note If you're following along with your code, you can change the pictures to files on your local machine, or you can get the pictures by downloading the Getting started with ListView sample (it's not the same sample, but it uses the same images). The sample will still run without adding the images.
Use the array to create a List object.
(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; var dataList = new WinJS.Binding.List(dataArray); })();
Expose the List by declaring a namespace and adding the List as a public member.
Because the code you just wrote is enclosed in an anonymous function, none of it is publicly accessible. That's part of the reason why you use the anonymous function: to keep private data private. For your ListView to be able to access the List, you must make it publicly accessible. One way to do this is to use the WinJS.Namespace.define function to create a namespace and add the List as one of its members.
The WinJS.Namespace.define function takes two parameters: the name of the namespace to create, and an object that contains one or more property/value pairs. Each property is the public name of the member, and each value is underlying variable, property, or function in your private code that you want to expose.
This example creates a namespace named DataExample that exposes a public member named itemList that returns your List.
(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; var dataList = new WinJS.Binding.List(dataArray); // Create a namespace to make the data publicly // accessible. var publicMembers = { itemList: dataList }; WinJS.Namespace.define("DataExample", publicMembers); })();
You created a data source that can be accessed by your ListView. Next, you connect the data to the ListView.
Connecting your data to the ListView
In the head section of the HTML file that contains your ListView, add a reference to the data file you just created (dataExample.js):
<head> <!-- Other file references ... --> <!-- Your data file. --> <script src="/js/dataExample.js"></script> </head>
Use the data you created in the last section to set the ListView control's itemDataSource property.
The itemDataSource property takes an IListDataSource object. The List object is not an IListDataSource, but it does have a dataSource property that returns an IListDataSource version of itself.
To connect your data, set the ListView control's itemDataSource property to
DataExample.itemList.dataSource
:<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource }"> </div>
Run the app. The ListView displays the properties and values in the data source:
This isn't quite the look that we want. We want to show just the values of the title and text field, and we want to show the actual images, not the path to the images. To get the rendering that we want, we need to define a Template. The next step shows you how.
Defining an item template
At this point, the ListView has the data it needs, but doesn't know how to display it. For that, you need an item template that contains the markup you want to use to display each list item. The item template can contain most other controls (for more info, see the Adding interactive elements section), but it can't contain a FlipView or another ListView.
There are two ways to create a template: you can use markup to define a WinJS.Binding.Template, or you can create a templating function. This example creates a template in markup. For info about creating a templating function, see the itemTemplate property.
A WinJS.Binding.Template is easy to create: you define the markup that you want to use to display each list item, then you indicate where each data field is displayed.
In your HTML, create a WinJS.Binding.Template control and assign it an ID. This example uses the ID "mediumListIconTextTemplate".
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> </div>
Note You must define your template before you use it, so add the HTML for our template before the HTML for your ListView.
WinJS.Binding.Template must have a single root element. Create a div element to serve as a parent for the template's contents.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div> </div> </div>
Create the markup that the ListView will produce for each data item it contains. The data you created in the previous step contains an image location, a title, and some text, so create these elements:
- An img element for displaying the picture field.
- An h4 element for displaying the title field.
- A h6 element for displaying the text field.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div> <!-- Displays the "picture" field. --> <img src="#" /> <div> <!-- Displays the "title" field. --> <h4></h4> <!-- Displays the "text" field. --> <h6></h6> </div> </div> </div>
To avoid layout problems, always specify the size of a template's root element, and always specify the size of img elements in the template.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" /> <div> <!-- Displays the "title" field. --> <h4></h4> <!-- Displays the "text" field. --> <h6></h6> </div> </div> </div>
Set the data-win-bind attribute on each element that displays data. The data-win-bind attribute uses the syntax:
data-win-bind="propertyName: dataFieldName"
For example, to bind the src property of an img to the "picture" field, use the syntax:
<img data-win-bind="src : picture" />
To set multiple properties, separate them with a semicolon:
data-win-bind="property1Name: dataField1Name; property2Name: dataField2Name"
This example binds the items in the template to their corresponding data fields.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" data-win-bind="alt: title; src: picture" /> <div> <!-- Displays the "title" field. --> <h4 data-win-bind="innerText: title"></h4> <!-- Displays the "text" field. --> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div>
To use the item template, use the select syntax to set the itemTemplate property of the ListView to your item template.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" data-win-bind="alt: title; src: picture" /> <div> <!-- Displays the "title" field. --> <h4 data-win-bind="innerText: title"></h4> <!-- Displays the "text" field. --> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div> <div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate')}"> </div>
Now when you run the app, the bound data appears in the list.
Styling the ListView
The ListView doesn't dynamically adjust its height to fit your content. For a ListView to render, you must specify an absolute value for its height. The WinJS style sheets set the ListView control's height to 400px, but it's easy to specify your own height by overriding the default style with your own CSS. Add this CSS to your app's CSS file to set the height and width of the ListView and give it a border:
ListView styling for Windows
.win-listview
{
height: 500px;
width: 500px;
border: 2px solid gray;
}
ListView styling for Windows Phone 8.1
.win-listview
{
height: 400px;
width: 300px;
border: 2px solid gray;
}
win-listview is a class defined by the WinJS that you can use to style the ListView. The example you just saw changes the height, width, and border of every ListView. To just change the one ListView, add the ID of the ListView control's hosting div element to the selector:
Specific ListView styling for Windows
#basicListView .win-listview
{
height: 500px;
width: 500px;
border: 2px solid gray;
}
Specific ListView styling for Windows Phone 8.1
#basicListView .win-listview
{
height: 400px;
width: 300px;
border: 2px solid gray;
}
Run the app. Now the ListView is big enough to display all the items.
The WinJS style sheets define CSS classes that you can override to customize the look and feel of a WinJS control. The CSS classes you use with ListView include:
win-listview
Specifies styles for the ListView itself.
win-container
Specifies styles for a ListView or FlipView item container. Each item has its own container.
win-progress
Specifies styles for the progress control that shows when the ListView is loading items.
For a complete list, see the ListView reference page.
This example defines a style that adds a margin around each item container in the ListView.
#basicListView .win-listview .win-container {
margin: 10px;
}
The next example defines a style that applies to list items in a ListView in the hover state.
#basicListView .win-listview .win-container:hover {
color: red;
}
Note
The ListView supports margins on its left, top, and bottom sides, but you can't specify a margin for its right side. One workaround is to add an element that's as wide as the margin you want and set its style.visibility property to "none", then add the element to the right of the ListView.
Styling items
The previous examples used inline styles and the WinJS classes to style your ListView and its items. You can also use CSS classes to style your item template. The next example updates the template you defined in the Defining an item template section. It removes the inline styles you defined and adds some CSS classes.
<div id="mediumListIconTextTemplate"
data-win-control="WinJS.Binding.Template"
style="display: none">
<div class="mediumListIconTextItem">
<img src="#" class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
<div class="mediumListIconTextItem-Detail">
<h4 data-win-bind="innerText: title"></h4>
<h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
Add these styles to your app's CSS:
.mediumListIconTextItem
{
width: 282px;
height: 70px;
padding: 5px;
overflow: hidden;
display: -ms-grid;
}
.mediumListIconTextItem img.mediumListIconTextItem-Image
{
width: 60px;
height: 60px;
margin: 5px;
-ms-grid-column: 1;
}
.mediumListIconTextItem .mediumListIconTextItem-Detail
{
margin: 5px;
-ms-grid-column: 2;
}
Here's what the ListView looks like now:
You don't have to create your template styles from scratch. For a set of commonly-used templates and their corresponding CSS, see Item templates for list layouts and Item templates for grid layouts.
Switching between list, grid, and cell layouts
The ListView element has three layout modes: list, grid, and cell.
To use the list layout, set the layout property to WinJS.UI.ListLayout, as shown here:
<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout: {type: WinJS.UI.ListLayout}}"> </div>
To use the grid layout, set the layout property to WinJS.UI.GridLayout, as shown here:
<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout: {type: WinJS.UI.GridLayout}}"> </div>
(Windows only) To use the cell layout, set the layout property to WinJS.UI.CellSpanningLayout, as shown here:
<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout: {type: WinJS.UI.CellSpanningLayout}}"> </div>
You can change the layout of a ListView at any time, even after you created it.
Grouping your data
You can group items in your ListView. This illustration shows items that are grouped alphabetically:
To learn how, see How to group items in a ListView.
Adding interactive elements to an item template
Note The item template can contain most other controls, but it can't contain a FlipView or another ListView.
Selecting and invoking ListView items
Normally, when the user interacts with an element, the ListView captures that interaction and uses it to determine whether the user selected or invoked an item or is panning through items. For an interactive element, such as a control, to receive input, you must attach the win-interactive
CSS class to the interactive element or one of its parent elements. That element and its children receive the interaction and no longer trigger events for the ListView.
When you attach the win-interactive
to an element in a item template, be sure that the element doesn't fill the entire item, otherwise the user won't have a way to select or invoke that item.
To add interactive elements to your item template, we recommend that you use a templating function instead of a WinJS.Binding.Template. For more info about templating functions, see How to create a templating function.
Adding reorder, drag, and drop functionality to a ListView (Windows only)
The ListView control also allows users to reorder, drag, and drop individual items. For instance, you can declare the drag functionality by setting the itemsDraggable property of the ListView to 'true'. Similarly, to allow users to reorder the items in the ListView control, you set the itemsReorderable property of the ListView to 'true'.
<div id="basicListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : DataExample.itemList.dataSource,
itemTemplate: select('#mediumListIconTextTemplate'),
itemsDraggable: true,
itemsReorderable: true }">
</div>
The itemsDraggable property allows individual items to be dragged visibly from the ListView control. When the user drags an item from the ListView, the itemdragstart event is raised. (This event is also raised at the beginning of a reorder operation.) When an item is dropped into the ListView, the ListView raises an itemdragdrop event.
For more information about adding reorder, drag, or drop functionality to a ListView control, see How to enable reordering, dragging, and dropping to a ListView or download the HTML ListView drag-and-drop and reordering sample.
ListView samples
For live code examples of nearly every WinJS control and an online editor, see try.buildwinjs.com.
These additional samples can help you learn more about the ListView control.
- Getting started with ListView sample
- ListView item templates sample
- ListView grouping and SemanticZoom sample
- StorageDataSource and GetVirtualizedFilesVector sample
Summary and next steps
You learned how to create a ListView, and bind it to data. You also learned how create and style item templates.
For a list of predefined item templates you can use in your app, see Item templates for list layouts and Item templates for grid layouts. To learn how to group items, see How to group items in a ListView.