角4可重复使用的组件和模板
我坚持在Angular 4中创建一个可重用的组件.我有一堆报告都包含一个搜索表单(每个报告的字段不同)和一个材料表结果列表(每个报告的字段列表不同).当我为每个报告复制整个组件时,它按预期工作,但我想将其重构为可重用的组件/模板和扩展它的子组件.但范围都是错误的,我无法理解这是如何工作的.
report.component.ts(可重用组件) import {Component,ViewChild} from '@angular/core'; import {MatPaginator} from '@angular/material'; import 'rxjs/add/operator/map'; import {ReportsDataSource} from '../services/reports-datasource.service'; @Component({ selector: 'app-report',templateUrl: './report.component.html',}) export class ReportComponent { @ViewChild(MatPaginator) paginator: MatPaginator; /** result table columns */ columns = []; /** Column definitions in order */ displayedColumns = this.columns.map(x => x.columnDef); /** empty search parameters object,used for form field binding */ /** datasource service */ dataSource: ReportsDataSource; /** submit the form */ getData() { this.dataSource.getData(); } } report.component.html(可重用模板) <form (ngSubmit)="getData()" #ReportSearchForm="ngForm"> <ng-content select=".container-fluid"></ng-content> <button type="submit" mat-button class="mat-primary" [disabled]="!ReportSearchForm.form.valid">Search</button> </form> <mat-table #table [dataSource]="dataSource"> <ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef"> <mat-header-cell *matHeaderCellDef>{{ column.header }}</mat-header-cell> <mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell> </ng-container> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> </mat-table> <mat-paginator #paginator [length]="dataSource ? dataSource.meta.total_results : 0" [pageSize]="dataSource ? dataSource.meta.per_page : 25" [pageSizeOptions]="[10,25,50,100]" > </mat-paginator> childreport.component.ts(特定报告) import {Component,OnInit} from '@angular/core'; import {ReportComponent} from '../report.component'; import {ChildreportService} from './childreport.service'; import {ReportsDataSource} from '../../services/reports-datasource.service'; @Component({ selector: 'app-report-child',templateUrl: './childreport.component.html',providers: [ChildreportService,ReportsDataSource] }) export class ChildreportComponent extends ReportComponent implements OnInit { constructor(private childreportService: ChildreportService) { super(); } /** result table columns */ columns = [ {columnDef: 'column1',header: 'Label 1',cell: (row) => `${row.column1}`},{columnDef: 'column2',header: 'Label 2',cell: (row) => `${row.column2}`} ]; ngOnInit() { this.dataSource = new ReportsDataSource(this.ChildreportService,this.paginator); } } childreport.component.html(此报告的搜索表单,嵌入在父模板中) <app-report> <div class="container-fluid"> <mat-form-field> <input matInput placeholder="some field" name="fieldx"> </mat-form-field> </div> </app-report> 什么有效:我得到主模板中嵌入的表单,没有错误. 什么不起作用:表单和表绑定到ReportComponent而不是ChildreportComponent.我有点理解为什么会发生这种情况(因为这个模板的范围是该组件)但我不知道如何“继承”模板并且在ChildreportComponent的范围内.我错过了什么? 解决方法
我自己想通了.事实上,解决方案相当简单.我的错误是在我的report.component中同时尝试两件事,提供模板和逻辑.我最终得到的是一个抽象组件,它包含逻辑并由每个报告扩展,以及每个报告中相似部分的几个较小组件(shell,结果列表等).我也从模板表单切换到反应表单.
report-base.component.ts包含通用逻辑 import {OnInit} from '@angular/core'; import {FormBuilder,FormGroup} from '@angular/forms'; import {MatPaginator,MatSidenav} from '@angular/material'; import 'rxjs/add/operator/map'; import {ReportsDataSource} from '../common/services/reports-datasource.service'; import {ReportsService} from '../common/services/reports.service'; import {ReportsResultlistService} from '../common/services/reports-resultlist.service'; export abstract class ReportBaseComponent implements OnInit { constructor( protected _formBuilder: FormBuilder,protected _reportService: ReportsService,protected _resultlistService: ReportsResultlistService) { } /** * For toggling the search form and resultlist action buttons * @type {boolean} */ protected hasResults = false; /** Default data source for the table */ protected dataSource: ReportsDataSource; /** search form controls */ protected searchForm: FormGroup; /** result table columns */ protected columns = []; ngOnInit() { this.createForm(); this.dataSource = new ReportsDataSource(this._reportService,this._resultlistService); } /** * Builds the searchForm Group */ protected createForm() { // create an empty form this.searchForm = this._formBuilder.group({}); } /** * Submits the form/loads data (f.ex. pagination) */ protected getData() { this.hasResults = true; this.dataSource.search = this.searchForm.value; this.dataSource.getData(); } } report-shell.component.ts是一个CHILD组件(我的一个逻辑错误),它提供了组件周围的shell: import {Component,Input} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @Component({ selector: 'app-report-shell',templateUrl: './report-shell.component.html',}) export class ReportShellComponent { constructor(private route: ActivatedRoute) { this.title = route.routeConfig.data['caption']; } @Input() hasResults = false; title: string; } report-shell.component.html提供搜索表单和结果列表周围的HTML <mat-expansion-panel [expanded]="!hasResults"> <mat-expansion-panel-header> Search </mat-expansion-panel-header> <ng-content select="form"></ng-content> </mat-expansion-panel> <div class="result-list"> <mat-toolbar class="result-header"><span>{{ title }}</span> <span class="fill-remaining-space"></span> <button class="fa fa-file-excel-o" (click)="exportExcel()"></button> </mat-toolbar> <ng-content select=".result-table"></ng-content> </div> 所以我的报告扩展了报告库,只需使用shell也是一个孩子: childreport.component.ts是一个特定的报告,仅实现此报告的特定报告 import {Component,OnInit} from '@angular/core'; import {FormBuilder,Validators} from '@angular/forms'; import {ReportChildreportService} from './childreport.service'; import {ReportsDataSource} from '../../common/services/reports-datasource.service'; import {ReportsResultlistService} from '../../common/services/reports-resultlist.service'; import {ReportBaseComponent} from '../report-base.component'; @Component({ selector: 'app-report-dispatches',templateUrl: './dispatches.component.html',providers: [ReportChildreportService,ReportsResultlistService,ReportsDataSource] }) export class ReportDispatchesComponent extends ReportBaseComponent implements OnInit { constructor(protected _reportService: ReportChildreportService,protected _formBuilder: FormBuilder,protected _resultlistService: ReportsResultlistService) { super(_formBuilder,_reportService,_resultlistService); } /** result table columns */ columns = [ {columnDef: 'name',header: 'Name',cell: (row) => `${row.name}`} ]; createForm() { this.searchForm = this._formBuilder.group({ name: '' }); } } childreport.component.html <app-report-shell [hasResults]="hasResults"> <form (ngSubmit)="getData()" [formGroup]="searchForm" novalidate> <mat-form-field> <input matInput placeholder="search for a name" name="name" formControlName="name"> <mat-error>Invalid name</mat-error> </mat-form-field> </div> </div> <app-form-buttons [status]="searchForm.status"></app-form-buttons> </form> <app-report-result-list [(dataSource)]="dataSource" [columns]="columns" [displayedColumns]="displayedColumns" class="result-table" ></app-report-result-list> </app-report-shell> 我不会详细介绍表单和结果列表组件,这个答案很长,因为它是:-) 所以我设法减少了很多代码重复,尽管仍然有一些(除了表单之外,还在childreport.component.html中). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |