How to use new Table State with model driven controls, paging and lazy loading?

UI Components for Angular
Post Reply
aflorin
Posts: 69
Joined: 13 Dec 2017, 19:01

10 Dec 2018, 20:25

I have a table with paging, lazy loading and model driven form controls and it isn't clear how to use the new Table State feature with those. Below is my HTML and TS code for a simple grid that displays user data fetched from my back end REST service. The TS code includes commented out code where I was using my own state object to store paging and filtering info.

I assumed with the new State functionality the table would automatically set its Event object's values based on the data stored in the defined session key and use it in the onlazyload method but that doesn't seem to be working correctly. Do I still need to set the table's first and filter properties onInit using the values via the session key? If so, all the new feature really saves me is just having to create my own object to store in session storage. I guess it also saves from having to bind to the onDeactivate event as well. Is that correct?

The HTML:

Code: Select all

<form novalidate [formGroup]="form" autocomplete="off">
    <p-card>
        <p-header>
            <div style="padding: 15px; padding-bottom: 0px; display: flex; flex-flow: row wrap; justify-content: space-between">
                <div style="flex: 0 1 auto">
                    <button pButton
                            type="button"
                            label="Add New"
                            class="ui-button-info"
                            icon="fa fa-plus"
                            style="width: auto"
                            [disabled]="!permission?.create"
                            (click)="addNew()"></button>
                </div>
                <div style="flex: 0 1 auto">
                    <button pButton
                            type="button"
                            label="Clear Filters"
                            class="ui-button-info"
                            style="width: auto"
                            icon="fa fa-undo"
                            (click)="clearFilters()"></button>
                </div>
            </div>
        </p-header>
        <p-table #usersTable
                 [value]="users"
                 [autoLayout]="true"
                 [(selection)]="selectedUser"
                 [alwaysShowPaginator]="false"
                 selectionMode="single"
                 [rows]="12"
                 [paginator]="true"
                 [lazy]="true"
                 [totalRecords]="totalUsers"
                 stateStorage="session"
                 stateKey="userGridTableState"
                 (onLazyLoad)="getUsers($event)"
                 (onRowSelect)="handleOnRowSelect($event)">
            <ng-template pTemplate="header">
                <tr>
                    <th>Name</th>
                    <th class="ui-p-4">Login ID</th>
                    <th class="ui-p-3">Email</th>
                    <th class="ui-p-3">Is Active</th>
                </tr>
                <tr>
                    <th class="ui-p-4">
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="fullName"
                               (input)="usersTable.filter($event.target.value, 'fullName', 'contains')">
                    </th>
                    <th>
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="userName"
                               (input)="usersTable.filter($event.target.value, 'userName', 'contains')">
                    </th>
                    <th class="ui-p-3">
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="email"
                               (input)="usersTable.filter($event.target.value, 'email', 'contains')">
                    </th>
                    <th class="ui-p-3">
                        <p-dropdown formControlName="isActive"
                                    appendTo="body"
                                    [options]="isActiveFilterOptions"
                                    [style]="{'width':'100%'}"
                                    (onChange)="usersTable.filter($event.value, 'isActive', 'equals')"></p-dropdown>
                    </th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-rowData let-user>
                <tr [pSelectableRow]="rowData">
                    <td style="text-align: center">{{user.fullName}}</td>
                    <td style="text-align: center" class="ui-p-4">{{user.userName}}</td>
                    <td style="text-align: center" class="ui-p-3">{{user.email}}</td>
                    <td style="text-align: center" class="ui-p-3">{{user.isActive ? 'Yes' : 'No'}}</td>
                </tr>
            </ng-template>
        </p-table>
    </p-card>
</form>
The TS code:

Code: Select all

// Angular
import {
    Component,
    OnInit,
    ViewChild
} from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
import {
    FormBuilder,
    FormGroup,
    FormControl
} from '@angular/forms';

// Vendor
import { CanComponentDeactivate } from 'app/core/services/deactivate-guard.service';
import { LazyLoadEvent } from 'primeng/primeng';
import { Table } from 'primeng/table';
import { MessageService } from 'primeng/components/common/messageservice';

// App
import { UserService } from 'app/features/user/user.service';
import { User, UserGridState } from 'app/features/user/user';
import { SessionStorageItems, Features, Screens, YesNoAllOptions } from 'app/core/constants';
import { PermissionService } from 'app/features/permission/permission.service';
import { Permission } from 'app/features/permission/permission';
import { NavigationTraceService } from 'app/features/navigation-trace/navigation-trace.service';

@Component({
    selector: 'drv-user-grid',
    templateUrl: './user-grid.component.html'
})
export class UserGridComponent implements
    OnInit,
    CanComponentDeactivate {

    @ViewChild('usersTable') usersTable: Table;

    form: FormGroup;
    isActiveFilterOptions: any[];
    users: User[];
    totalUsers: number;
    selectedUser: User = null;

    permission: Permission;

    get userNameControl(): FormControl {
        return this.form.get('userName') as FormControl;
    }
    get fullNameControl(): FormControl {
        return this.form.get('fullName') as FormControl;
    }
    get emailControl(): FormControl {
        return this.form.get('email') as FormControl;
    }
    get isActiveControl(): FormControl {
        return this.form.get('isActive') as FormControl;
    }

    constructor(
        private userService: UserService,
        private titleService: Title,
        private fb: FormBuilder,
        private router: Router,
        private messageService: MessageService,
        private permissionService: PermissionService,
        private navigationTraceService: NavigationTraceService
    ) {
        this.isActiveFilterOptions = YesNoAllOptions;
    }

    ngOnInit() {

        this.navigationTraceService
            .save(Screens.UserGrid)
            .subscribe(
                () => { },
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });

        this.titleService.setTitle('Red Oak: ' + Screens.UserGrid);

        this.users = [];

        this.form = this.fb.group({
            userName: [''],
            fullName: [''],
            email: [''],
            isActive: [''],
        });

        // If state info was stored (when user navigated away), reload the
        // filter controls and set the table's Filters object

        //let tableState = JSON.parse(sessionStorage.getItem(SessionStorageItems.UserGridState)) as UserGridState;

        //if (tableState) {
        //    this.userNameControl.setValue(tableState.userName);
        //    this.fullNameControl.setValue(tableState.fullName);
        //    this.emailControl.setValue(tableState.email);
        //    this.isActiveControl.setValue(tableState.isActive);
        //    this.usersTable.filters = tableState.filters;
        //    this.usersTable.first = tableState.pagingFirstIndex;
        //}

        //this.permissionService
        //    .getByFeature(Features.User)
        //    .subscribe(
        //        p => this.permission = p,
        //        error => this.messageService.add({
        //            severity: 'error',
        //            summary: 'Server Error',
        //            detail: error.message
        //        }));

        //tableState = null;

    }

    canDeactivate() {

        // Store the values in the filter controls in memory so they can be reset when
        // the component reloads when the use navigates back to the view

        //sessionStorage.setItem(
        //    SessionStorageItems.UserGridState,
        //    JSON.stringify(
        //        {
        //            userName: this.userNameControl.value,
        //            fullName: this.fullNameControl.value,
        //            email: this.emailControl.value,
        //            isActive: this.isActiveControl.value,
        //            pagingFirstIndex: this.usersTable.first,
        //            filters: this.usersTable.filters
        //        } as UserGridState)
        //);

        return true;
    }

    handleOnRowSelect(event) {
        this.router.navigate(['/' + Features.User + '/', event.data.id]);
    }

    clearFilters() {
        this.usersTable.reset();
        this.userNameControl.setValue('');
        this.fullNameControl.setValue('');
        this.emailControl.setValue('');
        this.isActiveControl.setValue('');
    }

    getUsers(event: LazyLoadEvent) {

        this.userService.getFilteredPage(
            event.first,
            event.first + event.rows,
            ('userName' in event.filters) ? (event.filters['userName'].value as string).trim() : '',
            ('fullName' in event.filters) ? (event.filters['fullName'].value as string).trim() : '',
            ('email' in event.filters) ? (event.filters['email'].value as string).trim() : '',
            ('isActive' in event.filters) ? event.filters['isActive'].value : 'All')
            .subscribe(
                (users: any) => {
                    this.users = [...users];
                },
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });

        this.userService.getTotal(
            ('userName' in event.filters) ? (event.filters['userName'].value as string).trim() : '',
            ('fullName' in event.filters) ? (event.filters['fullName'].value as string).trim() : '',
            ('email' in event.filters) ? (event.filters['email'].value as string).trim() : '',
            ('isActive' in event.filters) ? event.filters['isActive'].value : 'All')
            .subscribe(
                total => this.totalUsers = total,
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });
    }

    addNew() {
        this.router.navigate(['/' + Features.User + '/0']);
    }

}
Last edited by aflorin on 10 Dec 2018, 22:02, edited 1 time in total.

aflorin
Posts: 69
Joined: 13 Dec 2017, 19:01

10 Dec 2018, 21:51

It looks like indeed, the new table state feature basically just provides a built in session or local storage object that is automatically set when the component deactivates. So you in order to use lazy loading paging and model driver filter controls you still need to set the table's filter object as well as the the control values manually in the onInit event.

Here is my working code in case it helps anyone. The difference between this code and implementation I had used before was dropping my custom object where I was storing the values in session (now I'm using the table's object's built in session values accessed by the session key defined in the html) as well as dropping the onDeactivate route guard.

Code: Select all

<form novalidate [formGroup]="form" autocomplete="off">
    <p-card>
        <p-header>
            <div style="padding: 15px; padding-bottom: 0px; display: flex; flex-flow: row wrap; justify-content: space-between">
                <div style="flex: 0 1 auto">
                    <button pButton
                            type="button"
                            label="Add New"
                            class="ui-button-info"
                            icon="fa fa-plus"
                            style="width: auto"
                            [disabled]="!permission?.create"
                            (click)="addNew()"></button>
                </div>
                <div style="flex: 0 1 auto">
                    <button pButton
                            type="button"
                            label="Clear Filters"
                            class="ui-button-info"
                            style="width: auto"
                            icon="fa fa-undo"
                            (click)="clearFilters()"></button>
                </div>
            </div>
        </p-header>
        <p-table #usersTable
                 [value]="users"
                 [autoLayout]="true"
                 [(selection)]="selectedUser"
                 [alwaysShowPaginator]="false"
                 selectionMode="single"
                 [rows]="12"
                 [paginator]="true"
                 [lazy]="true"
                 [totalRecords]="totalUsers"
                 stateStorage="session"
                 stateKey="userGridTableState"
                 (onLazyLoad)="getUsers($event)"
                 (onRowSelect)="handleOnRowSelect($event)">
            <ng-template pTemplate="header">
                <tr>
                    <th>Name</th>
                    <th class="ui-p-4">Login ID</th>
                    <th class="ui-p-3">Email</th>
                    <th class="ui-p-3">Is Active</th>
                </tr>
                <tr>
                    <th class="ui-p-4">
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="fullName"
                               (input)="usersTable.filter($event.target.value, 'fullName', 'contains')">
                    </th>
                    <th>
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="userName"
                               (input)="usersTable.filter($event.target.value, 'userName', 'contains')">
                    </th>
                    <th class="ui-p-3">
                        <input pInputText
                               type="text"
                               style="width: 100%"
                               formControlName="email"
                               (input)="usersTable.filter($event.target.value, 'email', 'contains')">
                    </th>
                    <th class="ui-p-3">
                        <p-dropdown formControlName="isActive"
                                    appendTo="body"
                                    [options]="isActiveFilterOptions"
                                    [style]="{'width':'100%'}"
                                    (onChange)="usersTable.filter($event.value, 'isActive', 'equals')"></p-dropdown>
                    </th>
                </tr>
            </ng-template>
            <ng-template pTemplate="body" let-rowData let-user>
                <tr [pSelectableRow]="rowData">
                    <td style="text-align: center">{{user.fullName}}</td>
                    <td style="text-align: center" class="ui-p-4">{{user.userName}}</td>
                    <td style="text-align: center" class="ui-p-3">{{user.email}}</td>
                    <td style="text-align: center" class="ui-p-3">{{user.isActive ? 'Yes' : 'No'}}</td>
                </tr>
            </ng-template>
        </p-table>
    </p-card>
</form>

Code: Select all

// Angular
import {
    Component,
    OnInit,
    ViewChild
} from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
import {
    FormBuilder,
    FormGroup,
    FormControl
} from '@angular/forms';

// Vendor
import { LazyLoadEvent } from 'primeng/primeng';
import { Table } from 'primeng/table';
import { MessageService } from 'primeng/components/common/messageservice';

// App
import { UserService } from 'app/features/user/user.service';
import { User } from 'app/features/user/user';
import { Features, Screens, YesNoAllOptions } from 'app/core/constants';
import { PermissionService } from 'app/features/permission/permission.service';
import { Permission } from 'app/features/permission/permission';
import { NavigationTraceService } from 'app/features/navigation-trace/navigation-trace.service';

@Component({
    selector: 'drv-user-grid',
    templateUrl: './user-grid.component.html'
})
export class UserGridComponent implements
    OnInit {

    @ViewChild('usersTable') usersTable: Table;

    form: FormGroup;
    isActiveFilterOptions: any[];
    users: User[];
    totalUsers: number;
    selectedUser: User = null;

    permission: Permission;

    get userNameControl(): FormControl {
        return this.form.get('userName') as FormControl;
    }
    get fullNameControl(): FormControl {
        return this.form.get('fullName') as FormControl;
    }
    get emailControl(): FormControl {
        return this.form.get('email') as FormControl;
    }
    get isActiveControl(): FormControl {
        return this.form.get('isActive') as FormControl;
    }

    constructor(
        private userService: UserService,
        private titleService: Title,
        private fb: FormBuilder,
        private router: Router,
        private messageService: MessageService,
        private permissionService: PermissionService,
        private navigationTraceService: NavigationTraceService
    ) {
        this.isActiveFilterOptions = YesNoAllOptions;
    }

    ngOnInit() {

        this.navigationTraceService
            .save(Screens.UserGrid)
            .subscribe(
                () => { },
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });

        this.titleService.setTitle('Red Oak: ' + Screens.UserGrid);

        this.users = [];

        this.form = this.fb.group({
            userName: [''],
            fullName: [''],
            email: [''],
            isActive: [''],
        });

        // If state info was stored (when user navigated away), reload the
        // filter controls and set the table's Filters object

        let tableState = JSON.parse(sessionStorage.getItem('userGridTableState'));

        if (tableState) {

            if (tableState.filters) {
                this.userNameControl.setValue(tableState.filters.userName ? tableState.filters.userName.value : '');
                this.fullNameControl.setValue(tableState.filters.fullName ? tableState.filters.fullName.value : '');
                this.emailControl.setValue(tableState.filters.email ? tableState.filters.email.value : '');
                this.isActiveControl.setValue(tableState.filters.isActive ? tableState.filters.isActive.value : '');
                this.usersTable.filters = tableState.filters;
            }

            this.usersTable.first = tableState.first ? tableState.first : 0;
        }



        this.permissionService
            .getByFeature(Features.User)
            .subscribe(
                p => this.permission = p,
                error => this.messageService.add({
                    severity: 'error',
                    summary: 'Server Error',
                    detail: error.message
                }));


    }

    handleOnRowSelect(event) {
        this.router.navigate(['/' + Features.User + '/', event.data.id]);
    }

    clearFilters() {
        this.usersTable.reset();
        sessionStorage.removeItem('userGridTableState');
        this.userNameControl.setValue('');
        this.fullNameControl.setValue('');
        this.emailControl.setValue('');
        this.isActiveControl.setValue('');
    }

    getUsers(event: LazyLoadEvent) {

        this.userService.getFilteredPage(
            event.first,
            event.first + event.rows,
            ('userName' in event.filters) ? (event.filters['userName'].value as string).trim() : '',
            ('fullName' in event.filters) ? (event.filters['fullName'].value as string).trim() : '',
            ('email' in event.filters) ? (event.filters['email'].value as string).trim() : '',
            ('isActive' in event.filters) ? event.filters['isActive'].value : 'All')
            .subscribe(
                (users: any) => {
                    this.users = [...users];
                },
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });

        this.userService.getTotal(
            ('userName' in event.filters) ? (event.filters['userName'].value as string).trim() : '',
            ('fullName' in event.filters) ? (event.filters['fullName'].value as string).trim() : '',
            ('email' in event.filters) ? (event.filters['email'].value as string).trim() : '',
            ('isActive' in event.filters) ? event.filters['isActive'].value : 'All')
            .subscribe(
                total => this.totalUsers = total,
                error => {
                    this.messageService.add({
                        severity: 'error',
                        summary: 'Server Error',
                        detail: error.message
                    });
                });
    }

    addNew() {
        this.router.navigate(['/' + Features.User + '/0']);
    }

}

Post Reply

Return to “PrimeNG”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 18 guests