Every time I incorporate the mat-expansion-panel-header tag in my HTML, an error pops up in the console.
Referencing the basic expansion panel example from here.
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
I have included MatExpansionModule in module.ts.
Versions mentioned in package.json:
- "@angular/material": "^6.3.3",
- "@angular/material-moment-adapter": "^6.3.3",
- "typescript": "^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 { }
UPDATE: Including code snippets. It seems that even after modifying the HTML to match the standard expansion panel example, the issue persists. Link provided above for reference.