2017-10-10 65 views
1

我一直在开发一个使用Angular 2的应用程序,并且无可否认,这是一个作为新开发人员的努力。到目前为止,我已经管理了很多,但我确实需要一些帮助。我包含了一个plunkr,我用它作为引用来获取具有分页,筛选和排序的材料表,但此示例以及material.angular.io上的所有其他示例都显示了一个数据库示例本质上是硬编码/在组件类中生成的。我有一个服务,调用一个SQL查询的API,我想在这个例子中填充表格,但是到目前为止,我的尝试都是悲惨的失败,我想我已经在这个过程中压倒了自己。使用api调用实现材质表角度

通过请求我可以发布我的组件代码,但我担心我已经超出任何使用点的内脏/修改它。但在此之前,下面是我想要实现的plunkr,以及我希望用来填充数据表以代替plunkr的数据库和数据源的服务类。

请让我知道如果你能帮忙,你会为我节省一大笔头痛。

https://plnkr.co/edit/EU3BBlViWpPf2NJW4PXx?p=preview

我的服务

import { Injectable } from '@angular/core'; 
import { Http } from '@angular/http'; 
import 'rxjs/add/operator/map'; 


@Injectable() 
export class RcgqueueService { 

    constructor(private http: Http) { } 

    populateRCGQueue() { 
    return this.http.get('/api/rcgqueue').map(res => res.json()); 
    } 
} 

,并在组件代码

import { Component, ElementRef, ViewChild, OnInit, forwardRef } from '@angular/core'; 
import { DataSource, SelectionModel } from '@angular/cdk/collections'; 
import { MatPaginator, MatSort, MatTable } from '@angular/material'; 
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 
import { Observable } from 'rxjs/Observable'; 
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 { RcgqueueService } from './rcgqueue.service'; 

@Component({ 
    selector: 'app-rcgqueue', 
    templateUrl: './rcgqueue.component.html', 
    styleUrls: ['./rcgqueue.component.css'] 
}) 
export class RcgqueueComponent implements OnInit { 
    isDataAvailable = false; 
    displayedColumns = ['changeId', 'changeTitle', 'dateSubmitted', 'changeSponsor', 'changeDescription']; 
    dataChange: BehaviorSubject<ChangeData[]> = new BehaviorSubject<ChangeData[]>([]); 
    get data(): ChangeData[] { return this.dataChange.value; } 
    dataSource: ExampleDataSource | null; 

    @ViewChild(MatPaginator) paginator: MatPaginator; 
    @ViewChild(forwardRef(() => MatSort)) sort: MatSort; 
    @ViewChild('filter') filter: ElementRef; 

    constructor(private rcgservice: RcgqueueService) { 
    } 
    populateRCGQueue() { 
    this.rcgservice.populateRCGQueue().subscribe(rcgitems => { 
     this.dataChange = rcgitems; 
     this.isDataAvailable = true; 
    }) 
    } 

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

export interface ChangeData { 
    ChangeId: string; 
    ChangeTitle: string; 
    DateSubmitted: string; 
    ChangeSponsor: string; 
    ChangeDescription: string; 
} 

/** 
* Data source to provide what data should be rendered in the table. Note that the data source 
* can retrieve its data in any way. In this case, the data source is provided a reference 
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage 
* the underlying data. Instead, it only needs to take the data and send the table exactly what 
* should be rendered. 
*/ 
export class ExampleDataSource extends DataSource<any> { 
    _filterChange = new BehaviorSubject(''); 
    get filter(): string { return this._filterChange.value; } 
    set filter(filter: string) { this._filterChange.next(filter); } 

    dataChange: BehaviorSubject<ChangeData[]> = new BehaviorSubject<ChangeData[]>([]); 
    get data(): ChangeData[] { return this.dataChange.value; } 

    filteredData: ChangeData[] = []; 
    renderedData: ChangeData[] = []; 

    constructor(private rcgcomponent: RcgqueueComponent, 
    private _paginator: MatPaginator, 
    private _sort: MatSort) { 
    super(); 

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

    /** Connect function called by the table to retrieve one stream containing the data to render. */ 
    connect(): Observable<ChangeData[]> { 
    // Listen for any changes in the base data, sorting, filtering, or pagination 
    const displayDataChanges = [ 
     this.rcgcomponent.dataChange, 
     this._sort.sortChange, 
     this._filterChange, 
     this._paginator.page, 
    ]; 

    return Observable.merge(...displayDataChanges).map(() => { 
     // Filter data 
     this.filteredData = this.rcgcomponent.data.slice().filter((item: ChangeData) => { 
     const searchStr = (item.ChangeDescription + item.ChangeSponsor).toLowerCase(); 
     return searchStr.indexOf(this.filter.toLowerCase()) !== -1; 
     }); 

     // Sort filtered data 
     const sortedData = this.sortData(this.filteredData.slice()); 

     // Grab the page's slice of the filtered sorted data. 
     const startIndex = this._paginator.pageIndex * this._paginator.pageSize; 
     this.renderedData = sortedData.splice(startIndex, this._paginator.pageSize); 
     return this.renderedData; 
    }); 
    } 

    disconnect() { } 

    /** Returns a sorted copy of the database data. */ 
    sortData(data: ChangeData[]): ChangeData[] { 
    if (!this._sort.active || this._sort.direction === '') { return data; } 

    return data.sort((a, b) => { 
     let propertyA: number | string = ''; 
     let propertyB: number | string = ''; 

     switch (this._sort.active) { 
     case 'changeId': [propertyA, propertyB] = [a.ChangeId, b.ChangeId]; break; 
     case 'changeTitle': [propertyA, propertyB] = [a.ChangeTitle, b.ChangeTitle]; break; 
     case 'dateSubmitted': [propertyA, propertyB] = [a.DateSubmitted, b.DateSubmitted]; break; 
     case 'changeSponsor': [propertyA, propertyB] = [a.ChangeSponsor, b.ChangeSponsor]; break; 
     case 'changeDescription': [propertyA, propertyB] = [a.ChangeDescription, b.ChangeDescription]; break; 
     } 

     const valueA = isNaN(+propertyA) ? propertyA : +propertyA; 
     const valueB = isNaN(+propertyB) ? propertyB : +propertyB; 

     return (valueA < valueB ? -1 : 1) * (this._sort.direction === 'asc' ? 1 : -1); 
    }); 
    } 
} 

我已经去除了具有与选择从该表从plunkr做任何事情,我现在可怜的企图代码,这里剩下的就是我目前的位置。如果结果比阻碍更有帮助,我很抱歉。

哦,这可能会有帮助,我的api.js在服务器端与我正在使用的查询。 (唯一一个至今)

const express = require('express'); 
const async = require('async'); 
const jwt = require('jsonwebtoken'); 
const shape = require('shape-json'); 
const router = express.Router(); 

var sql = require('mssql/msnodesqlv8'); 
var config = { 
    driver: 'msnodesqlv8', 
    connectionString: 'Driver=SQL Server Native Client 11.0;Server=localhost;Database=Change;Trusted_Connection=yes;', 
} 

var conn = new sql.ConnectionPool(config); 
conn.connect().then(function() { 
    log("Change Governance Database Connection opened"); 
}).catch(function (err) { 
    console.error(new Date() + " - Issue connecting to the MS SQL database.", err); 
}); 

router.get('/', (req, res) => { 
    res.send('api works'); 
}); 

router.get('/rcgqueue', (req, res) => { 
    new sql.Request(conn) 
    .query('SELECT ChangeId, ChangeTitle, DateSubmitted, ChangeSponsor, ChangeDescription FROM dbo.ChangeEvaluationForm;') 
    .then(function(recordset) { 
     log("Successful query request for RCG Records."); 
     res.send(recordset.recordset); 
    }).catch(function(err) { 
     log(err); 
     res.send("Issue querying database!"); 
    }); 
}); 

/********************************/ 
/*   Functions   */ 
/********************************/ 
// Log lines with date/time for server 
function log(msg) { 
    console.log(new Date() + " - " + msg); 
}; 

module.exports = router; 

编辑:添加模板和错误。

模板

<!-- Issues 
https://github.com/angular/angular/issues/16614 
https://github.com/angular/angular/issues/17572 --> 
<div *ngIf="isDataAvailable"> 
    <div class="example-container mat-elevation-z8"> 
    <div class="example-header"> 
     <md-input-container floatPlaceholder="never"> 
     <input mdInput #filter placeholder="Filter"> 
     </md-input-container> 
    </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" --> 

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

     <!-- ChangeTitle Column --> 
     <ng-container cdkColumnDef="changeTitle"> 
     <md-header-cell *cdkHeaderCellDef md-sort-header> Change Title </md-header-cell> 
     <md-cell *cdkCellDef="let row"> {{row.ChangeTitle}}% </md-cell> 
     </ng-container> 

     <!-- DateSubmitted --> 
     <ng-container cdkColumnDef="dateSubmitted"> 
     <md-header-cell *cdkHeaderCellDef md-sort-header> Date Submitted </md-header-cell> 
     <md-cell *cdkCellDef="let row"> {{row.DateSubmitted}} </md-cell> 
     </ng-container> 

     <!-- ChangeSponsor --> 
     <ng-container cdkColumnDef="changeSponsor"> 
     <md-header-cell *cdkHeaderCellDef md-sort-header> Change Sponsor </md-header-cell> 
     <md-cell *cdkCellDef="let row"> {{row.ChangeSponsor}} </md-cell> 
     </ng-container> 

     <!-- ChangeDescription --> 
     <ng-container cdkColumnDef="changeDescription"> 
     <md-header-cell *cdkHeaderCellDef md-sort-header> Change Description </md-header-cell> 
     <md-cell *cdkCellDef="let row"> {{row.ChangeDescription}} </md-cell> 
     </ng-container> 

     <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row> 
     <md-row *cdkRowDef="let row; columns: displayedColumns;"> 
     </md-row> 
    </md-table> 

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

    <md-paginator #paginator [length]="dataSource.filteredData.length" [pageIndex]="0" [pageSize]="25" [pageSizeOptions]="[5, 10, 25, 100]"> 
    </md-paginator> 
    </div> 
</div> 

最后我的错误

enter image description here

+0

您正在使用哪种版本的角材料? – yurzui

+0

4.4.3如果需要,我可以在我的package.json中给出依赖关系。 – David

+0

您是否收到任何错误? – yurzui

回答

5

原因的截图,为什么你越来越

Cannot set property pageIndex of undefined

是你包表*ngIf和您通过的时间对于DataSource类,它们尚未初始化210秒。

我解决它通过获取数据后,调用初始化:

this.rcgservice.populateRCGQueue().subscribe(rcgitems => { 
    this.dataChange.next(rcgitems); 
    this.isDataAvailable = true; 
    this.cdRef.detectChanges(); // make sure that all ViewChilds were initialized 
    this.initSource(); 

另一个错误是分配数据BehaviourSubject

this.rcgservice.populateRCGQueue().subscribe(rcgitems => { 
    this.dataChange = rcgitems; 

它应该是:

this.dataChange.next(rcgitems); 

我也将一些安全的导航操作员添加到您的模板中:

[length]="dataSource?.filteredData.length" 

[style.display]="dataSource?.renderedData.length == 0 ? '' : 'none'" 

Plunker Example

如果我们不使用ngIf那么我们就不需要再ChangeDetectorRef

Plunker Example

+0

我无法表达我多么感激你的时间和精力。我现在正在经历一切,只要我能确认一切正常,就会将其标记为答案。 – David

+0

不客气!另外看看第二个跳伞者 – yurzui

+0

它像梦一样运作。再一次感谢你。 – David