我自己想出来的。事实上,解决方案相当简单。我的错误是在报告中同时尝试了两件事。组件,提供模板和逻辑。我最终得到的是一个抽象组件,它包含逻辑,并由每个报告扩展,以及每个报告中类似部分的几个较小组件(shell、结果列表等)。我还从模板表单切换到反应表单。
报告库。组成部分输电系统
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) {
}
protected hasResults = false;
protected dataSource: ReportsDataSource;
protected searchForm: FormGroup;
protected columns = [];
ngOnInit() {
this.createForm();
this.dataSource = new ReportsDataSource(this._reportService, this._resultlistService);
}
protected createForm() {
this.searchForm = this._formBuilder.group({});
}
protected getData() {
this.hasResults = true;
this.dataSource.search = this.searchForm.value;
this.dataSource.getData();
}
}
报告外壳。组成部分输电系统
是一个子组件(我的逻辑错误之一),它为组件提供外壳:
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;
}
提供搜索表单和结果列表周围的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:
是仅实现此报告特定内容的特定报告
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);
}
columns = [
{columnDef: 'name', header: 'Name', cell: (row) => `${row.name}`}
];
createForm() {
this.searchForm = this._formBuilder.group({
name: ''
});
}
}
儿童报告。组成部分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中也有重复)。