角<mat-expansion-panel-header>不会加载

时间:2018-10-04 14:05:05

标签: angular typescript angular-material

每当我在html中使用标签mat-expansion-panel-header时,控制台中都会出现错误。

使用https://material.angular.io/components/expansion/overview基本的扩展面板示例。

ERROR TypeError: Cannot read property 'pipe' of undefined
at new MatExpansionPanelHeader (expansion.es5.js:326)
at createClass (core.js:9103)
at createDirectiveInstance (core.js:8978)
at createViewNodes (core.js:10198)
at callViewAction (core.js:10514)
at execComponentViewsAction (core.js:10433)
at createViewNodes (core.js:10226)
at createRootView (core.js:10112)
at callWithDebugContext (core.js:11143)
at Object.debugCreateRootView [as createRootView] (core.js:10630)
View_TrainingOptionsComponent_0 @ TrainingOptionsComponent.html:25

我在module.ts中有MatExpansionModule。

package.json中的版本:

  • “ @角度/材料”:“ ^ 6.3.3”,
  • “ @ angular / material-moment-adapter”:“ ^ 6.3.3”,
  • “打字稿”:“ ^ 2.7.2”

<div fxLayoutAlign="space-between stretch" class="options-list-container">
          <div class="options-list">
            <mat-divider class="mat-divider"></mat-divider>
            <mat-accordion *ngFor="let option of filteredHeaders" class="option mat-accordion" data-id="{{option.id}}">
              <mat-expansion-panel #optionPanel>
                <mat-expansion-panel-header class="mat-expansion-panel-header">
                  <mat-panel-title fxFlex.lg="70" fxFlex.xs="70" fxFlex.md="70">
                    {{option.title}}
                  </mat-panel-title>
                  <mat-panel-title fxFlex.lg="15" fxFlex.xs="70" fxFlex.md="70">
                    {{option.dateFrom | date:'dd-MM-yyyy'}}
                  </mat-panel-title>
                  <mat-panel-title class="status" fxFlex.lg="15" fxFlex.xs="15">
                    {{option.price}} + ~{{option.additionalPrice}} EUR
                  </mat-panel-title>
                </mat-expansion-panel-header>
                <app-option-details *ngIf="optionPanel._getExpandedState() === 'expanded'"
                                    [id]="option.id"
                                    (dateEmitter)="getDates($event)">

                </app-option-details>
                <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
                  <div fxFlex="50" fxLayout.lt-lg="100" fxLayoutAlign="start center">
                    <button mat-raised-button color="primary" (click)="openEditOption(option.id); editMode = true">EDIT OPTION</button>
                  </div>
                  <div fxFlex="100" fxLayout.lt-lg="100" fxLayoutAlign="end center">
                    <button mat-raised-button color="primary" (click)="openDialog(option);">APPLY</button>
                  </div>
                </div>
              </mat-expansion-panel>
            </mat-accordion>
          </div>
        </div>

component.ts

import { Component, OnInit } from '@angular/core';
import { trigger, style, animate, transition } from '@angular/animations'
import { HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { MatDialog } from '@angular/material';
import { ITrainingOption } from '../shared/trainingOption.model';
import { ISelector } from '../shared/selector.model';
import { IOptionHeader } from '../shared/optionHeader.model';
import { ApiService } from '../shared/api.service';
import { FormGroup, FormControl } from '@angular/forms';
import { ApplicationsComponent } from './applications/applications.component';
import { MomentDateAdapter, MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';

export const dateFormat = {
  parse: {
    dateInput: 'l',
  },
  display: {
    dateInput: 'l',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'l',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

export interface IIsInternalSelect {
  value: boolean;
  viewValue: string;
}

@Component({
  selector: 'app-options',
  templateUrl: './training-options.component.html',
  styleUrls: ['./training-options.component.scss'],
  providers: [
    {
      provide: DateAdapter,
      useClass: MomentDateAdapter,
      deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS, MAT_DATE_FORMATS]
    },
    {
      provide: MAT_DATE_FORMATS,
      useValue: dateFormat
    },
    { provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
    { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }
  ],
  animations: [
    trigger(
      'enterAnimation', [
        transition(':enter',
          [
            style({ transform: 'translateX(100%)' }),
            animate('400ms', style({ transform: 'translateX(0)' }))
          ]),
        transition(':leave', [
          style({ transform: 'translateX(0)' }),
          animate('200ms', style({ transform: 'translateX(100%)' }))
        ])
      ]
    )
  ],
})

export class TrainingOptionsComponent implements OnInit {
  constructor(private apiService: ApiService, public dialog: MatDialog) { }

  ngOnInit(): void {
    this.getCategories();
    this.getEventTypes();
    this.getHeaders();
  }

  form = new FormGroup({
    id: new FormControl(),
    title: new FormControl(),
    link: new FormControl(),
    description: new FormControl(),
    categoryId: new FormControl(),
    periodFrom: new FormControl(),
    periodTo: new FormControl(),
    price: new FormControl(),
    additionalPrice: new FormControl(),
    eventTypeId: new FormControl(),
    isInternal: new FormControl(),
    isFullDay: new FormControl(),
    createdById: new FormControl()
  });

  isAddOptionShown: boolean;
  minDateFrom: Date = new Date();
  minDate: Date;
  maxDate: Date;

  categories: ISelector[] = [];
  eventTypes: ISelector[] = [];
  headers: IOptionHeader[] = [];
  filteredHeaders: IOptionHeader[] = [];
  optionDates: Date[] = [];

  organizerTypes: IIsInternalSelect[] = [
    { value: true, viewValue: 'Internal' },
    { value: false, viewValue: 'External' }
  ];

  openDialog(option: IOptionHeader): void {
    this.dialog.open(ApplicationsComponent, {
      data: {
        opt: option,
        dates: this.optionDates
      }
    });
  }

  set searchString(value: string) {
    this.filteredHeaders = value ? this.performFilter(value) : this.headers;
  }

  performFilter(filterBy: string): IOptionHeader[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.headers.filter((header: IOptionHeader) =>
      header.title.toLocaleLowerCase().indexOf(filterBy) !== -1);
  }

  submitOption(option: ITrainingOption) {
    this.apiService.addOrUpdateOption(option).subscribe(() => {
      this.isAddOptionShown = false;
      this.getHeaders();
    });
  }

  getHeaders() {
    this.apiService.getTrainingOptionHeaders().subscribe(
      x => {
        this.headers = x;
        this.filteredHeaders = x;
      }
    );
  }

  getCategories() {
    this.apiService.getCategories().subscribe(
      categories => {
        this.categories = categories;
      });
  }

  getEventTypes() {
    this.apiService.getEventTypes().subscribe(
      eventTypes => {
        this.eventTypes = eventTypes;
      });
  }

  openEditOption(editOptionId: number) {
    this.apiService.getTrainingOption(editOptionId).subscribe(x => {
      this.form.setValue({
        'id': x.id,
        'title': x.title,
        'description': x.description,
        'link': x.link,
        'categoryId': x.categoryId,
        'eventTypeId': x.eventTypeId,
        'isInternal': x.isInternal,
        'price': x.price,
        'additionalPrice': x.additionalPrice,
        'periodFrom': x.periodFrom,
        'periodTo': x.periodTo,
        'isFullDay': x.isFullDay,
        'createdById': x.createdById
      });
      this.isAddOptionShown = true;
      this.minDateFrom = x.periodFrom;
      this.minDate = x.periodFrom;
      this.maxDate = x.periodTo;
    });
  }

  getDates(dates: Date[]) {
    this.optionDates = dates;
  }

  resetForm() {
    this.form.setValue({
      'id': 0,
      'title': '',
      'description': '',
      'link': '',
      'categoryId': '',
      'eventTypeId': '',
      'isInternal': false,
      'price': 0,
      'additionalPrice': 0,
      'periodFrom': null,
      'periodTo': null,
      'isFullDay': false,
      'createdById': '.'
    });
    this.minDateFrom = new Date();
    this.minDate = this.minDateFrom;
    this.maxDate = null;
  }
}

module.ts

import {
  MatExpansionModule,
  MatButtonModule,
  MatButtonToggleModule,
  MatInputModule,
  MatToolbarModule,
  MatIconModule,
  MatListModule,
  MatSelectModule,
  MatDatepickerModule,
  MatNativeDateModule,
} from '@angular/material';
import { MatChipsModule } from '@angular/material/chips';
import { CoreModule } from '../core/core.module';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TrainingOptionsComponent } from './training-options.component';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatCardModule } from '@angular/material/card';
import { CommonModule } from '@angular/common';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ApplicationsComponent } from './applications/applications.component';
import { TrainingRequestsModule } from '../training-requests/training-requests.module';

export const appRoutes: Routes = [
  { path: '', component: TrainingOptionsComponent },
  { path: 'application', component: ApplicationsComponent }
];

@NgModule({
  imports: [
    MatCardModule,
    FlexLayoutModule,
    MatButtonModule,
    MatButtonToggleModule,
    MatInputModule,
    MatToolbarModule,
    MatIconModule,
    MatCheckboxModule,
    MatListModule,
    MatChipsModule,
    MatSelectModule,
    MatDatepickerModule,
    MatNativeDateModule,
    MatExpansionModule,
    CoreModule,
    CommonModule,
    RouterModule.forChild(appRoutes),
    FormsModule,
    ReactiveFormsModule,
    TrainingRequestsModule
  ],
  declarations: [TrainingOptionsComponent, ApplicationsComponent],
  exports: [],
})
export class TrainingOptionsModule { }

编辑:添加了代码。为了记录,即使我将html更改为基本扩展面板示例的html也无法正常工作。链接在第二行。

2 个答案:

答案 0 :(得分:1)

可能的原因是您在@angular/material@angular/cdk版本中不匹配。

它们必须是完全相同的版本。

来源:Github issue comment

答案 1 :(得分:0)

共享该HTML结构以及该组件的TypeScript代码也可能会有所帮助。

在最基本的情况下,您只需要在module.ts上导入和导出MatExpansionModule,然后只需在<mat-expansion-panel>标记内编写正确的HTML标记即可。

似乎您正在尝试对未正确定义的信息使用管道。因此,正如我所说,如果您共享HTML的外观,将会很有帮助。