Angular 2 Material Table Serverside Paging

时间:2017-08-31 13:32:54

标签: angular angular-material

我对Angular 2 Material Table和服务器端分页有问题。我的问题是我无法等待我的Datascource-object的connect函数中的异步请求调用。我尝试了很多方法,但没办法。结果总是表显示具有先前偏移和限制的数据。我知道在异步调用之后我有一个返回但没有这些返回会得到一个observable的错误(这是尝试获取新数据而不是以前的数据的点)。我的功能目标是获得服务器端分页。我希望你能帮助我。

我的component.ts:

import { Component, ViewChild, ElementRef } from '@angular/core';
import { UserService } from './user.service';
import { LanguagePipe } from './../system/language/language.pipe';
import { generateUUID } from './../helper/helper.component';
import { DialogComponent } from "../dialog/dialog.component";
import { generatePassword } from "./../password/passwordGenerator";
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap';
import { SharedService } from './../shared/shared.service';
import { FunctionPermissionService } from './../system/permission/functionpermission.service';
import { RoleListComponent } from "./../role/rolelist.component";
import { FunctionsPermission } from './../system/globals/globals.service';
import { MdTableModule } from '@angular/material';
import { DataSource } from '@angular/cdk';
import { MdPaginator, MdSort, SelectionModel } from '@angular/material';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/debounceTime';
import { Role } from "./user.class";


@Component({
    selector: 'user',
    templateUrl: './user.component.html',
    styleUrls: ['./user.component.scss'],
})
export class TableSortingExample {
    displayedColumns = ['select', 'firstname', 'email', 'phonenumber', 'roles'];
    userDatabase: UserDatabase;
    selection = new SelectionModel<string>(true, []);
    dataSource: ExampleDataSource | null;

    @ViewChild(MdPaginator) paginator: MdPaginator;
    @ViewChild(MdSort) sort: MdSort;
    @ViewChild('filter') filter: ElementRef;

    constructor(
        private userService: UserService,
        private languagePipe: LanguagePipe,
        private sharedService: SharedService,
        private functionPermissionService: FunctionPermissionService
    ) {

    }
    ngOnInit() {
        this.getUser().then(data => {
            console.log(data);
            this.userDatabase = new UserDatabase(data, this.userService);
            this.getUserCount().then((data: any) => {
                this.dataSource = new ExampleDataSource(this.userDatabase, this.paginator, this.sort, this.userService, data);

            })

        })
        Observable.fromEvent(this.filter.nativeElement, 'keyup')
            .debounceTime(150)
            .distinctUntilChanged()
            .subscribe(() => {
                if (!this.dataSource) { return; }
                this.dataSource.filter = this.filter.nativeElement.value;
            });


    }

    isAllSelected(): boolean {
        if (!this.dataSource) { return false; }
        if (this.selection.isEmpty()) { return false; }

        if (this.filter.nativeElement.value) {
            return this.selection.selected.length == this.dataSource.renderedData.length;
        } else {
            return this.selection.selected.length == this.userDatabase.data.length;
        }
    }

    masterToggle() {
        if (!this.dataSource) { return; }

         if (this.isAllSelected()) {
             this.selection.clear();
         } else if (this.filter.nativeElement.value) {
             this.dataSource.renderedData.forEach(data => this.selection.select(data.id));
         } else {
             this.userDatabase.data.forEach(data => this.selection.select(data.id));
         }
    }


    getUser() {
        let papingString = "offset=" + 0 + "&limit=" + 5;

        return new Promise((resolve, reject) => {
            this.userService.getAdministrativeUser("", papingString).subscribe(data => {
                resolve(data);
            }, err => {
                console.error(err);
                reject(err);

            }, () => { });
        });

    }

    getUserCount() {
        return new Promise((resolve, reject) => {
            this.userService.getAdministrativeUserSize('').subscribe((data: any) => {
                resolve(data);
            }, err => {
                console.error(err);
                reject(err);

            }, () => { });
        });

    }
}

export interface UserData {
    id: string;
    firstname: string;
    email: string;
    phonenumber: string;
    roles: Array<Role>;
}

/** An example database that the data source uses to retrieve data for the table. */
export class UserDatabase {
    /** Stream that emits whenever the data has been modified. */
    pagingString = "";
    userData: UserData[];
    dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
    get data(): UserData[] {return this.dataChange.value;}

    constructor(data: any, private userService: UserService) {
        console.log(data);
        this.fillDatabase(data);
    }

    /** Adds a new user to the database. */
    fillDatabase(data: any) {
        console.log(data);
        const copiedData = data.slice();
        for (let entry of data)
            copiedData.push(convertUser(entry));

        this.dataChange.next(copiedData);
    }

    getData(extra: string) {
        return new Promise((resolve, reject) => {
            this.userService.getAdministrativeUser("", extra).subscribe(data => {
                let userData: Array<UserData> = [];
                for (let entry of data)
                    userData.push(convertUser(entry));
                resolve(userData);
            }, err => {
                console.error(err);
                reject(err);
            });
        });
    }
}


export class ExampleDataSource extends DataSource<any> {
    _filterChange = new BehaviorSubject('');
    get filter(): string { return this._filterChange.value; }
    set filter(filter: string) { this._filterChange.next(filter); }

    filteredString: string = "";
    prevFilteredString: string = "";
    prevSortDirection: string = "";
    prevSortField: string = "";
    renderedData: UserData[] = [];
    change: boolean = false;
    subject: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
    constructor(private _exampleDatabase: UserDatabase,
        private _paginator: MdPaginator,
        private _sort: MdSort,
        private userService: UserService,
        private dataCount: number) {
        super();

        this._filterChange.subscribe(() => this._paginator.pageIndex = 0);
    }

    connect(): Observable<UserData[]> {
        const displayDataChanges = [
            this._exampleDatabase.dataChange,
            this._sort.mdSortChange,
            this._filterChange,
            this._paginator.page,
        ];


        return Observable.merge(...displayDataChanges).map(() => {
            if (this.prevFilteredString != this.filter) {
                this._paginator.pageIndex = 0;
                this._exampleDatabase.data.splice(0, this._exampleDatabase.data.length);
            }
            // Filtering
            if (this.filter != null && this.filter != "" && this.filter != undefined)
                this.filteredString = "&filter=(firstname like '%" + this.filter + "%' or lastname like '%" + this.filter + "%' or phonenumber like '%" + this.filter + "%' or email like '%" + this.filter + "%')";
            this.prevFilteredString = this.filter;

            // Sorting
            const sortInformations = this.sortData();


            let pageIndex = this._paginator.pageIndex;
            const startIndex = pageIndex * this._paginator.pageSize;

            let pagingString = "offset=" + startIndex + "&limit=" + this._paginator.pageSize + this.filteredString + sortInformations;


            this._exampleDatabase.pagingString = pagingString;
            this.getDataCount(this.filteredString + sortInformations);

            this.getData(pagingString).then((data:any) =>{
                console.log(this._exampleDatabase.data);
                this._exampleDatabase.data.splice(0, this._exampleDatabase.data.length);
                for(let entry of data)
                    this._exampleDatabase.data.push(entry); 
                this.renderedData = this._exampleDatabase.data.slice();
                console.log(this._exampleDatabase.data);

                return this._exampleDatabase.data.slice();
            },err => {
                console.error(err);
            });

            return this._exampleDatabase.data.slice();
        });


    }

    disconnect() { console.log("test"); }

    getDataCount(extra: string) {
        return new Promise((resolve, reject) => {
            if (extra.charAt(0) === '&') {
                extra = extra.substr(1);
            }
            this.userService.getAdministrativeUserSize(extra).subscribe(data => {
                this.dataCount = data;
                resolve();
            });
        })

    }
    getData(extra: string) {
        return new Promise((resolve, reject) => {
            this.userService.getAdministrativeUser("", extra).subscribe(data => {
                let userData: Array<UserData> = [];
                for (let entry of data)
                    userData.push(convertUser(entry));
                resolve(userData);
            }, err => {
                console.error(err);
                reject(err);
            });
        });
    }
    /** Returns a sorted copy of the database data. */
    sortData(): string {
        if (!this._sort.active) {
            if (this._sort.direction != this.prevSortDirection || "" != this.prevSortField)
                this._paginator.pageIndex = 0;
        } else
            if (this._sort.direction != this.prevSortDirection || this._sort.active.toString() != this.prevSortField)
                this._paginator.pageIndex = 0;

        if (!this._sort.active || this._sort.direction == '') {
            this.prevSortDirection = "";

            if (!this._sort.active)
                this.prevSortField = ""
            else
                this.prevSortField = this._sort.active;
            return "";

        } else {
            this.prevSortDirection = this._sort.direction.toString();
            this.prevSortField = this._sort.active.toString();
            return "&order=" + this._sort.active.toString() + " " + this._sort.direction.toString()
        };
    }
}
/** Builds and returns a new User. */
export function convertUser(data: any) {
    let user: UserData = {
        id: data.id,
        firstname: data.firstname,
        email: data.email,
        phonenumber: data.phonenumber,
        roles: []
    }
    let userRoles: Array<Role> = [];
    for (let role of data.roles)
        userRoles.push(new Role(role.name, role.id));

    user["roles"] = userRoles;
    return user;
};

我的HTML:

<div class="example-container mat-elevation-z8">
  <div class="example-header" [style.display]="selection.isEmpty() ? '' : 'none'">
    <md-input-container floatPlaceholder="never">
      <input mdInput #filter placeholder="Filter users">
    </md-input-container>
  </div>
  <div class="example-header example-selection-header"
       *ngIf="!selection.isEmpty()">
    {{selection.selected.length}}
    {{selection.selected.length == 1 ? 'user' : 'users'}}
    selected
  </div>

  <md-table #table [dataSource]="dataSource" mdSort>

    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->

    <!-- Checkbox Column -->
    <ng-container cdkColumnDef="select">
      <md-header-cell *cdkHeaderCellDef>
      </md-header-cell>
      <md-cell *cdkCellDef="let row">
        <md-checkbox (click)="$event.stopPropagation()"
                     (change)="$event ? selection.toggle(row.id) : null"
                     [checked]="selection.isSelected(row.id)">
        </md-checkbox>
      </md-cell>
    </ng-container>

    <!-- ID Column -->
    <ng-container cdkColumnDef="firstname">
      <md-header-cell *cdkHeaderCellDef md-sort-header> Name </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.firstname}} </md-cell>
    </ng-container>

    <!-- Progress Column -->
    <ng-container cdkColumnDef="email">
      <md-header-cell *cdkHeaderCellDef md-sort-header> Email </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.email}} </md-cell>
    </ng-container>

    <!-- Name Column -->
    <ng-container cdkColumnDef="phonenumber">
      <md-header-cell *cdkHeaderCellDef md-sort-header> Phonenumber </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.phonenumber}} </md-cell>
    </ng-container>

    <!-- Color Column -->
    <ng-container cdkColumnDef="roles">
      <md-header-cell *cdkHeaderCellDef md-sort-header> Rolen </md-header-cell>
      <md-cell *cdkCellDef="let row"> <label *ngFor="let role of row.roles">{{role.name}}</label> </md-cell>
    </ng-container>

    <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
    <md-row *cdkRowDef="let row; columns: displayedColumns;"
             [class.example-selected-row]="selection.isSelected(row.id)"
             (click)="selection.toggle(row.id)">
    </md-row>
  </md-table>

  <div class="example-no-results"
       [style.display]="( datasource == null || dataSource.renderedData.length == 0 )? '' : 'none'">
    No users found matching filter.
  </div>

  <md-paginator #paginator
                [length]="(dataSource == null)?0:dataSource.dataCount"
                [pageIndex]="0"
                [pageSize]="5"
                [pageSizeOptions]="[5, 10]">
  </md-paginator>
</div>

班级档案:

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';

export class rowItem {
    constructor(
        public userInformations: UserInformations,
        public roles: Array<Role>) {

    }

    setRoles(input: Array<Role>) {
        this.roles = input;
    }
    setUserInformation(input: UserInformations) {
        this.userInformations = input;
    }
    getIdList(): Array<string> {
        let result: Array<string> = [];
        for (let role of this.roles)
            result.push(role.id);
        return result;
    }
}
export class UserInformations {
    constructor(
        public id: string,
        public firstname: string,
        public lastname: string,
        public email: string,
        public phonenumber: string) {

    }
}
export class Role {
    constructor(public name: string, public id: string) {

    }
}

我的css文件:

/* Structure */
.example-container {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.example-header {
  min-height: 56px;
  max-height: 56px;
  display: flex;
  align-items: center;
  padding: 8px 24px 0;
  font-size: 20px;
  justify-content: space-between;
  border-bottom: 1px solid transparent;
}

.mat-input-container {
  font-size: 14px;
  flex-grow: 1;
  margin-left: 32px;
  margin-top: 8px;
}

.example-no-results {
  display: flex;
  justify-content: center;
  padding: 24px;
  font-size: 12px;
  font-style: italic;
}

/** Selection styles */
.example-selection-header {
  font-size: 18px;
  background: rgba(255, 64, 129, 0.3);
  border-bottom: 1px solid #d696ac;
}

.mat-column-select {
  max-width: 54px;
}

.mat-row:hover, .example-selected-row {
  background: #f5f5f5;
}

.mat-row:active, .mat-row.example-selected-row {
  background: #eaeaea;
}

.mat-table {
  overflow: auto;
  max-height: 500px;
}

0 个答案:

没有答案