List View

The list-view controller renders items of a list using a component or view template associated to each item.
It supports the following list rendering modes:

  • full:
    the full items list is rendered in one pass
  • incremental:
    items are appended to the list as the list is being scrolled down
  • paginated:
    items list is organized into browsable pages

Regardless of the selected mode, the generated list consists of simple empty div containers with a fixed height matching the height of the associated components, and that are later replaced with the actual components when they are about to become visible in the scroll area (components loaded lazily).

Components preload threshold can be adjusted using the zuix.lazyLoad(..) method.

Example

Client-side rendered list of 500 components from a JSON data file.

Page
try Example on CodePen

Usage

1. Import list-view module

<script type="module">
import "https://zuixjs.github.io/zkit/lib/1.2/controllers/list-view.module.js";
</script>

2. Add component

Add the list-view component:

<list-view z-context="my-list-view"
:items-per-page="50"
:list-mode=" 'incremental' "
:model="myDataSource"
:adapter="myDataAdapter">
</list-view>

1. Include zuix.js library

If not already included, add the following line right before the end of the head section in the HTML document:

<script src="https://cdn.jsdelivr.net/npm/zuix-dist@1.1.13/js/zuix.min.js"></script>

2. Load the list-view controller

Add the ctrl z-load attributes to the element hosting the list-view:

<div ctrl z-load="https://zuixjs.github.io/zkit/lib/1.2/controllers/list-view"
z-context="my-list-view"
:items-per-page="50"
:list-mode=" 'incremental' "
:model="myDataSource"
:adapter="myDataAdapter">

</div>

Option attributes

  • z-context="<context_id>" identifier name to be used to access this component from JavaScript.
  • :on:<event_name>="<handler>" optional
    set handler function for event <event_name>
  • :list-mode optional
    list mode can be full, incremental or paginated. The default value is full.
  • :items-per-page optional pages to load for a single page. Works for paginated and incremental modes. The default value is 30.
  • :model
    sets the data model (array of items) that will be used to render the list
  • :adapter
    sets the adapter callback that will return the component configuration for a given (index, item) pair.

Events

  • list:busy()
    the list view is busy rendering
  • list:ready()
    the list view is ready
  • list:update(e, info)
    data has been updated
  • list:end
    end of list reached
  • page:change(e, info)
    page changed

The info object passed to the list:update and page:change events, has the following format:

{
"page": {
"current": 0,
"count": 17
},
"items": {
"current": 8,
"loaded": 9,
"count": 500
}
}

Infinite scroll

When the list:end event occurs, more data can be added to the feed to implement infinite scroll:

listView.on('list:end', () => {
// fetch more data
// ...
listView.model().push(...newData);
});

Scripting

The data :model and the :adapter callback

The data items passed to the :model option, is an array of objects that can be of any type.
Then, the :adapter callback will be called as needed by the list-view controller for each item that is being rendered to get all required data to display the item.

const myDataAdapter = (index, item) => ({
componentId: item.componentId,
type: item.type,
options: {
on: {click: (e, data, $el) => console.log('clicked', $el)},
model: item.model
},
className: item.className
});

In the data returned by the adapter, the componentId field sets the component or template to be used to display the item.

For example, an inline/banner-example template, can be defined with the following HTML code:

<template z-view="inline/banner-example">

<div #title class="title"></div>
<div #text class="text"></div>

<style>
:host {
background-color: white;
}
.title {
font-size: 200%;
color: deeppink;
}
.text {
padding: 12px;
}
</style>

</template>

The above template will be applied to each item with componentId set to inline/banner-example, and the content of the two divs with the #title and #text attributes, will be replaced with the corresponding fields in the data returned as model by the data adapter.

The other fields returned by the data adapter, type and options are also required to create the component.
The type attribute must be set to view in case the componentId is a view template, like in this example, or it can be omitted if it's a regular component with also a .js controller.
With the options object it's possible to set the data passed to the component by using the options.model field.
A complete description of all options fields is available in the zuix.js Context Options documentation.

The className is an optional but strongly recommended parameter for best performance. It sets a name of a CSS class that will be added to the component's container, so that the container will have the same size of the rendered component even if it's not loaded yet.

Getting a reference to the list-view component:

zuix.context('my-list-view', (lv) => {
// store a global reference for later use
self.listView = lv;
});

Methods

// sets the list-view mode and items per page
listView.config({
listMode: 'paginated',
itemsPerPage: 50,
data: myDataSource,
adapter: myDataAdapter
});

// get the data model
const data = listView.model();
// add more data
data.push(...newData);

// clear all items
listView.clear();

When mode is set to paginated, the following methods can be used:

// go to current page or get current page if no argument is specified
listView.page(4);
let currentPage = listView.page();

// goto previous page
listView.prev();

// goto next page
listView.next();

When mode is incremental, the following method can be used

// load more items
listView.more();
arrow_left  Previous
Next arrow_right 
Support this work
extension
zKit components v1.2.1
web enhancing bits