* Icons used in this sample are provided by icons8.com
a suite of UI Components for development of web apps
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Advanced User Interface Controls and Components
Created: 19 September 2016
Updated: 24 March 2017
IntegralUI ListView is a native Angular 2 component that displays list of items either in horizontal or vertical layout. Items can be reordered using advanced drag drop operations. You can load data on demand during run-time from local or remote data sources, and add custom HTML content in each item. In following sections, you can find details about various features available in the ListView component.
* Icons used in this sample are provided by icons8.com
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Above demonstration shows two different views:
In addition, item content is arranged differently: horizontal layout shows item content in one line, while vertical layout shows item content in a box.
You can reorder items by click and drag over specific item. A dragging window will appear, stating the target item and position at which item can be dropped. During drag drop operations, you can also create a copy of an item by holding the SHIFT key. The dragging window will change its icon, showing a + sign next to position marker.
In order to use the ListView component in your app, you need to do the following:
To specify how you want items to be arranged, use the scrollMode property, which can accept one of two values: 'horizontal' or 'vertical':
//
// main.ts file
//
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
//
// app.module.ts file
//
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { IntegralUIModule } from 'integralui/integralui.module';
@NgModule({
imports: [ BrowserModule, IntegralUIModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
//
// app.component.ts file
//
import { Component, ViewEncapsulation } from '@angular/core';
import { IntegralUIScrollMode } from './integralui/components/integralui.core';
@Component({
selector: 'iui-app',
templateUrl: 'app.template.html',
styleUrls: ['listview-overview.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
// Get a reference of application view
@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;
// Get a reference of ListView component
@ViewChild('listview') listview: IntegralUIListView;
// An Array object that holds all item objects shown in ListView
// It is set as a list of any custom objects, you can use any custom fields and bind them with ListView using its properties
private items: Array<any>;
private scrollType: IntegralUIScrollMode = IntegralUIScrollMode.Horizontal;
private currentSelection = null;
// Initialize items in component constructor
constructor(){
this.items = [
{ id: 1, icon: "sci-fi", text: "Star Trek", year: "2009", rating: 8.1 },
{ id: 2, icon: "adventure", text: "Cast Away", year: "2000", rating: 7.7 },
{ id: 3, icon: "action", text: "Gladiator", year: "2000", rating: 8.5 },
{ id: 4, icon: "drama", text: "Malèna", year: "2000", rating: 7.5 },
{ id: 5, icon: "music", text: "Moulin Rouge", year: "2001", rating: 7.6 },
{ id: 6, icon: "comedy", text: "Snatch", year: "2000", rating: 8.3 },
{ id: 7, icon: "biography", text: "A Beautiful Mind", year: "2001", rating: 8.2 },
{ id: 8, icon: "crime", text: "Black Hawk Down", year: "2001", rating: 7.7 },
{ id: 9, icon: "western", text: "Django Unchained", year: "2012", rating: 8.5 },
{ id: 10, icon: "sci-fi", text: "Man of Steel", year: "2013", rating: 7.2 },
{ id: 11, icon: "horror", text: "The Ring", year: "2002", rating: 7.1 },
{ id: 12, icon: "romance", text: "40 Days and 40 Nights", year: "2002", rating: 5.6 },
{ id: 13, icon: "sci-fi", text: "Minority Report", year: "2002", rating: 7.7 },
{ id: 14, icon: "comedy", text: "Scary Movie 3", year: "2003", rating: 5.5 },
{ id: 15, icon: "music", text: "Walk the Line", year: "2005", rating: 7.9 },
{ id: 16, icon: "romance", text: "How to Lose a Guy in 10 Days", year: "2003", rating: 6.4 },
{ id: 17, icon: "crime", text: "The Dark Knight", year: "2008", rating: 9.1 },
{ id: 18, icon: "horror", text: "American Psycho", year: "2000", rating: 7.6 },
{ id: 19, icon: "drama", text: "The Grand Budapest Hotel", year: "2014", rating: 8.1 },
{ id: 20, icon: "comedy", text: "The Wolf of Wall Street", year: "2013", rating: 8.2 }
];
}
isScrollHorizontal(){
return this.scrollType == IntegralUIScrollMode.Horizontal ? true : false;
}
isScrollVertical(){
return this.scrollType == IntegralUIScrollMode.Vertical ? true : false;
}
scrollTypeClicked(flag?: boolean){
if (flag)
this.scrollType = IntegralUIScrollMode.Vertical;
else
this.scrollType = IntegralUIScrollMode.Horizontal;
}
getRating(value){
if (this.scrollType == IntegralUIScrollMode.Horizontal)
return "../resources/star.png";
else {
let stars = Math.floor(value / 2);
return "../resources/stars-small-" + stars + ".png";
}
}
getRatingValue(value){
return Math.floor(value);
}
private horItemStyle = {
general: {
normal: 'item'
}
}
private verItemStyle = {
general: {
normal: 'item',
selected: 'item-selected'
}
}
itemSelectionChanged(item){
this.currentSelection = item;
}
}
bootstrap(AppComponent);
//
// app.template.html file
//
<div #application>
<div>
<label><input type="radio" [checked]="isScrollHorizontal()" (click)="scrollTypeClicked()" />Horizontal</label>
<label><input type="radio" [checked]="isScrollVertical()" (click)="scrollTypeClicked(true)" />Vertical</label>
</div>
<iui-listview [items]="items" [appRef]="applicationRef" [scrollMode]="scrollType" (selectionChanged)="itemSelectionChanged($event)" #listview>
<div *ngIf="scrollType == 'horizontal'">
<iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="horItemStyle">
<div class="custom-item" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span class="rating">{{getRatingValue(item.rating)}}</span>
<span class="num">{{i+1}}.</span>
<span class="icons {{item.icon}}"></span>
<span class="title">{{item.text}}</span>
<img class="star" src="{{getRating(item.rating)}}" />
</div>
</iui-listitem>
</div>
<div *ngIf="scrollType == 'vertical'">
<iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="verItemStyle">
<div class="custom-item-large" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span *ngIf="item == currentSelection" class="corner"></span>
<span class="num-corner">{{i+1}}</span><br />
<div class="icon-large">
<span class="icons {{item.icon}}"></span>
</div>
<span class="title-large">{{item.text}}</span><br />
<img class="star-inline" src="{{getRating(item.rating)}}" />
</div>
</iui-listitem>
</div>
</iui-listview>
</div>
/*
listview-overview.css file
*/
.iui-listview
{
width: 400px;
height: 400px;
}
.num
{
display: inline-block;
vertical-align: middle;
}
.num-corner
{
display: inline-block;
font-size: 0.875em;
margin: -3px 0 0 -3px;
position: relative;
vertical-align: middle;
z-index: 1;
}
.corner
{
content: "";
border: 20px solid #357ebd;
border-color: #357ebd transparent transparent #357ebd;
position: absolute;
top: -5px;
left: -5px;
width: 0;
height: 0;
z-index: 0;
}
.title
{
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
width: 50%;
}
.icons
{
background: url(../resources/movie-genres.png) no-repeat 0 0;
display: inline-block;
padding: 0;
margin: 3px;
width: 24px;
height: 24px;
vertical-align: middle;
}
.action
{
background-position: 0 0;
}
.adventure
{
background-position: -24px 0;
}
.comedy
{
background-position: -48px 0;
}
.action
{
background-position: -72px 0;
}
.sci-fi
{
background-position: -120px 0;
}
.biography
{
background-position: 0 -24px;
}
.horror
{
background-position: -24px -24px;
}
.drama
{
background-position: -48px -24px;
}
.music
{
background-position: -72px -24px;
}
.romance
{
background-position: -96px -24px;
}
.western
{
background-position: -120px -24px;
}
.star
{
display: inline-block;
float: right;
vertical-align: middle;
}
.rating
{
display: inline-block;
font-weight: bold;
font-size: 0.75em
position: absolute;
top: 18px;
right: 20px;
vertical-align: middle;
}
.item
{
display: inline-block;
}
.custom-item
{
border: thin solid #e9e9e9;
margin: 0;
overflow: hidden;
padding: 5px;
text-overflow: ellipsis;
width: 180px;
white-space: nowrap;
}
.custom-item-large
{
border: thin solid #e9e9e9;
margin: 0;
overflow: hidden;
padding: 5px;
position: relative;
width: 100px;
white-space: nowrap;
z-index: 0;
}
.title-large
{
color: black;
display: inline-block;
overflow: hidden;
padding: 3px 0;
text-overflow: ellipsis;
width: 100%;
vertical-align: middle;
}
.star-inline
{
display: inline-block;
vertical-align: middle;
}
.icon-large
{
padding: 10px;
margin: 0 auto;
width: 24px;
}
.item-selected
{
background-color: transparent;
border-color: #357ebd !important;
color: white;
}
Note If you want to show item with different content then other items, you can use the ngIf directive and set condition by which a different content will appear.
In this example, each item has an icon, label, rating and index. Depending on which layout is currently active, the item content is arranged either in one line or in a box.
Furthermore, the visual appearance of items is also changed. By using controlStyle property, you can set up custom CSS classes that will override default appearance of items.
private horItemStyle = {
general: {
normal: 'item'
}
}
private verItemStyle = {
general: {
normal: 'item',
selected: 'item-selected'
}
}
<iui-listview [items]="items" [appRef]="applicationRef" [scrollMode]="scrollType" (selectionChanged)="itemSelectionChanged($event)" #listview>
<div *ngIf="scrollType == 'horizontal'">
<iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="horItemStyle">
<div class="custom-item" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span class="rating">{{getRatingValue(item.rating)}}</span>
<span class="num">{{i+1}}.</span>
<span class="icons {{item.icon}}"></span>
<span class="title">{{item.text}}</span>
<img class="star" src="{{getRating(item.rating)}}" />
</div>
</iui-listitem>
</div>
<div *ngIf="scrollType == 'vertical'">
<iui-listitem *ngFor="let item of items; let i = index" [controlStyle]="verItemStyle">
<div class="custom-item-large" (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span *ngIf="item == currentSelection" class="corner"></span>
<span class="num-corner">{{i+1}}</span><br />
<div class="icon-large">
<span class="icons {{item.icon}}"></span>
</div>
<span class="title-large">{{item.text}}</span><br />
<img class="star-inline" src="{{getRating(item.rating)}}" />
</div>
</iui-listitem>
</div>
</iui-listview>
.item
{
display: inline-block;
}
.item-selected
{
background-color: transparent;
border-color: #357ebd !important;
color: white;
}
All properties of the ListView component can be set using a separate attribute that is linked to an object in your application scope or to a specified value.
Here is a list of available properties:
To avoid using plain javascript manipulation of the DOM and because of the way Angular 2 is structured, in order to show a tooltip, context menu or any other popup window, a reference to the root application component is required. You can provide a value to appRef property by simply setting a variable to the root component, and then access it by calling the ViewChild with specified variable name.
// Get a reference of application view
@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;
<div #application>
<iui-listview [items]="items" [appRef]="applicationRef">
<iui-listitem *ngFor="let item of items">
{{item.text}}
</iui-listitem>
</iui-listview>
</div>
If you want to have a specified item selected initially, you can set the selectedItem property to point to the item object in your data source.
When you have a custom data source tat may differ from internal data settings of ListView component, you can use data binding which will match the names of data fields in your data source with those used by the ListView.
By specifying the items property to point to your data object, along with dataFields property that holds an object that maps the names of fields in the data object, you can populate the ListView using any kind of custom data source.
This feature is also usable when you need to load data on demand in the ListView, from a remote data source.
When interacting with the ListView component, depending on the action, a corresponding event is fired. For example adding an item will fire itemAdding and itemAdded events, selecting an item will fire beforeSelect, afterSelect and selectionChanged events, etc.
Here is a list of available events:
By handling these events in your code, you can add custom actions that may alter the default behavior of the ListView component. For example, by handling the dragOver event, you can exclude a specified item as a target during drag drop operation, by setting a condition.
In some cases, you may need to add new items or remove existing items in the ListView during run-time. For this purpose, there are built-in methods available that allow you to change the structure of the ListView:
//
// app.component.ts file
//
export class AppComponent {
// An Array object that holds all item objects shown in ListView
private data: Array
// Get a reference to the ListView component using a variable set in HTML
@ViewChild('listview') listview: IntegralUIListView;
// Initialize items in component constructor
constructor(){
this.data = [];
}
// Adds a new item to the end of the ListView
addItem(){
this.listview.addItem({ text: "Item " + (this.data.length+1).toString() });
}
// Fired whenever a new item is added to the ListView
itemAddedEvent(e){
if (e.item)
console.log("itemAdded: " + e.item.text);
}
}
bootstrap(AppComponent);
//
// app.template.html file
//
<iui-listview [items]="data" (itemAdded)="itemAddedEvent($event)" #listview>
<iui-listitem *ngFor="let item of items">
{{item.text}}
</iui-listitem>
</iui-listview>
In above code, we are adding a new item with some items using the addItem method. To access this method, at first we need to get a reference to the ListView component. In HTML we are adding the #listview variable, which is used to locate the ListView within your application component.
After we have a reference to the ListView component, we can get access to all public methods available:
When you have large data source, you can populate the ListView by using virtualization. This allows you to load thousands of records into the ListView component and work in the client. To enable this mode, set the virtualMode property to true.
ListView component comes with advanced drag drop that allows you to reorder items by simply dragging one or multiple items from one place to another within the same or other components.
During this process, events are fired that can help you to add custom actions that may alter the default built-in drag drop functionality. In each event, you can set up custom conditions that can prevent or allow drag drop in special cases, depending on your application requirements.
Whenever an item is dragged, a dragging window will appear showing the target item and position at which item can be dropped. There are three possible positions:
By default, during drag and drop items are moved from their original position to a new one. In some cases, instead of moving you may need to create a copy of dragged items. Copy operation is already built-in, you only need to press and hold the SHIFT key, when item is dropped. The dragging window will change its icon showing a + sign. This states that copy of dragged item will drop at specified position.
Each part of IntegralUI ListView component is fully customizable. There are different CSS classes for each component part. Although changing the attributes of built-in classes is possible, you can completely override them using the controlStyle property.
The controlStyle property accpets an object that holds all or partial list of CSS class names that will override the default CSS class names. For each component part, a different CSS class governs its appearance. This allows you to specify a set of different CSS classes for each component part and alter the appearance of the ListView in whole. In this way, you can make it more suitable for your application requirements.
IntegralUI ListView component allows you to display items in horizontal or vertical layout, and allows reordering during run-time using drag drop operations. You can populate the ListView using custom data source, locally or remotely.
By default, each item contains an icon and a label. By adding custom HTML elements or other Angular components as item content, you can create custom view of the ListView component.
The ListView component is part of IntegralUI Web.