Angular ListView with Data from a Custom JSON File

Created: 30 Sep 2019

In most cases, data fields that you are using may be different from the ones used by the IntegralUI ListView component for Angular. To solve this, you need to map the names of your data objects to the ones that are already in use by the ListView. This articles presents a demo how to do that using a custom JSON data.

ListView component is part of IntegralUI Web
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

In this example, the ListView shows items in a way similar to the Tools view in Acrobat Reader. Each item has an icon, title and a dropdown menu with different options. The LIstView is populated from a JSON file with data that includes items in whole: that is an icon, label and content of the dropdown menu.

How to Bind Custom Data Fields in Angular ListView

When your data has different field names, prior populating the ListView you need to map the data fields with the ones that are already in use. This is only required field names that are already predefined, like id, text etc. For example, if your items use a 'name' field instead of 'text' field (both a related to displaying item label), than you need to map it.

Data binding is simple; you can use the dataFields property of the angular ListView component. This property accepts an object that replaces the default field names with your own. First, here is a list of fields that are already in use (as predefined):

     dataFields = {
        allowDrag: 'allowDrag',
        allowDrop: 'allowDrop',
        allowEdit: 'allowEdit',
        allowFocus: 'allowFocus',
        canSelect: 'canSelect',
        enabled: 'enabled',
        expanded: 'expanded',
        icon: 'icon',
        id: 'id',
        selected: 'selected',
        style: 'style',
        text: 'text',
        value: 'value',
        visible: 'visible'
    }
                    

For most of these field names, you don't need a data binding. The most important ones are id, text and value. These fields are related to the item unique identifier, its label and custom object as its value. Text and value fields are also important for sorting.

In this example, we have a JSON data where the most used field names: id and text are changed with new names. As you can see from code, the listFields object replaces the id to itemId, text to label. There are also custom data fields, like dropdown that holds information about the dropdown menu.

public listFields: any = {
    icon: 'icon',
    id: 'itemId',
    text: 'label'
}
                            
<div class="app-block" #application>
    <iui-listview [controlStyle]="ctrlStyle" [dataFields]="listFields" [items]="items" (selectionChanged)="itemSelected($event)" #listview>
        <iui-listitem [controlStyle]="itemStyle" *ngFor="let item of items" [data]="item" [controlStyle]="itemStyle">  
            <div class="lview-dfjson-item-content">
                <div class="lview-dfjson-item-top-content">
                    <div class="lview-dfjson-item-icon">
                        <span class="lview-dfjson-icons {{item.icon}}"></span>
                    </div>
                    <span class="lview-dfjson-item-label">{{item.label}}</span><br />
                </div>
                <div class="lview-dfjson-item-dropdown">
                    <iui-dropdown-button [controlStyle]="dropDownStyle" [direction]="dropDownDirection" [settings]="item.dropdown" (itemClick)="dropDownItemClicked($event, item)">{{item.dropdown.label}}</iui-dropdown-button>
                </div>
            </div>
        </iui-listitem>
    </iui-listview>
</div>
                            

Note Note When a new field names are in use, you also need to update the item template to reflect the change. Template is based on the item object from your data source.

How to Populate the ListView with Custom JSON Data

Once we have the data binding set up, you can load the data from the JSON file in the angular ListView. For this purpose, you can use the angular http service, like in this example.

The demo above presents a ListView component with a list of items where each item displays an icon, label and a dropdown menu at the bottom. All items are arranged in horizontal layout, which means scrolling is only horizontal. The dropdown menu is customizable, you can have a different one for each item or share it.

Note Note Once the data is retrieved from a local or remote JSON file, prior loading it in the ListView component it is a good practice to suspend any updates of the component layout. This increases the loading performance.

private loadFromJSON(){
    let self = this;

    // Use HTTP service to get data from the specified JSON file
    self.http.get("./assets/file.json").subscribe((data: Array) => {
        // Suspend the tree layout from updates, to increase performance
        self.listview.suspendLayout();

        // Load data into the list view
        self.listview.loadData(data, self.listFields);

        // Or , you can apply the new data to the items property directly (commented out)
        // self.items = data;
        

        self.items.map(item => {
            if (item.dropdown){
                item.dropdown.appRef = this.applicationRef;
            }
        });

        // Resume and update the tree layout
        self.listview.resumeLayout();
    });
}
                            
[
    { "itemId": 1, "label": "Comment", "icon": "notes", "dropdown": { "adjustment": { "top": 2, "left": 80 }, "label": "Open", "items": [{ "text": "Open" }, { "text": "Learn More" }] } },
    { "itemId": 2, "label": "Protect", "icon": "shield", "dropdown": { "adjustment": { "top": 2, "left": 86 }, "label": "Add", "items": [{ "text": "Add" }, { "text": "Learn More" }] } },

        // . . .
        // 
        // You can find the full content of this file in sample project on StackBlitz: https://stackblitz.com/edit/integralui-listview-data-fields-json
                            

To load the data into the ListView, you can use the built-in loadData method or set the new data directly to the items property. At last, you need to update the component layout to reclect the changes. You can do this with updateLayout method or if the layout is previously suspended, to resume it use the resumeLayout method.

Adding a DropDown Menu to Items in ListView

As a dropdown menu, in this case we are using the IntegralUI DropDown directive. This directive is attachable to any element or component and allows you to display a popup window with custom content: it can be a list or a panel that can contain any custom HTML elements arranged in layout defined by a template on your side.

The most important setting here is the appRef field of the dropdown object. This field must contain a reference to the top element in your app, so that the popup content appears on top of all other elements. As you can see from the code, you can get this reference by providing a variable name in the top div element and then use the angular ViewContainerRef to get a reference to it.

@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;

ngAfterViewInit(){
    // Load data into the ListView from a JSON file
    this.loadFromJSON();

    this.dropDownSettings = {
        adjustment: { top: 1, left: 30 },
        appRef: this.applicationRef
    }
}

dropDownItemClicked(e: any, obj: any){
    console.log(e.item.text + " is clicked from item: ", obj);
}

                            
<div class="app-block" #application>
    <iui-listview [controlStyle]="ctrlStyle" [dataFields]="listFields" [items]="items" (selectionChanged)="itemSelected($event)" #listview>
        <iui-listitem [controlStyle]="itemStyle" *ngFor="let item of items" [data]="item" [controlStyle]="itemStyle">  
            <div class="lview-dfjson-item-content">
                <div class="lview-dfjson-item-top-content">
                    <div class="lview-dfjson-item-icon">
                        <span class="lview-dfjson-icons {{item.icon}}"></span>
                    </div>
                    <span class="lview-dfjson-item-label">{{item.label}}</span><br />
                </div>
                <div class="lview-dfjson-item-dropdown">
                    <iui-dropdown-button [controlStyle]="dropDownStyle" [direction]="dropDownDirection" [settings]="item.dropdown" (itemClick)="dropDownItemClicked($event, item)">{{item.dropdown.label}}</iui-dropdown-button>
                </div>
            </div>
        </iui-listitem>
    </iui-listview>
</div>
                            

Conclusion

Data binding in IntegralUI ListView for Angular is simple. When your data source uses different names from the ones used by the list view, you can map your data fields by providing an object that matches the data names. This allows you to keep the format of your data intact and populate the ListView component from local or remote data source.

The ListView component is part of IntegralUI Web.

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.