制作简化的 angular material 手风琴,但未捕获输出事件
Making a simplified angular material accordion, but Output event is not caught
我正在尝试通过制作我自己的版本来简化 angular material 手风琴,该版本试图稍微简化它。
我有一个 步进器组件:
<mat-accordion>
<ng-content>
</ng-content>
</mat-accordion>
这个很简单,有这些方法:
import {
Component,
AfterViewInit,
QueryList,
ContentChildren,
OnDestroy,
Input
} from "@angular/core";
import { StepComponent } from "./step.component";
import { Subscription } from "rxjs";
@Component({
selector: "app-stepper",
templateUrl: "./stepper.component.html",
styleUrls: ["./stepper.component.scss"]
})
export class StepperComponent implements AfterViewInit, OnDestroy {
@Input() closeOthers: boolean = true;
@ContentChildren(StepComponent) children: QueryList<any>;
step = 0;
private subscriptions: Subscription = new Subscription();
constructor() {}
ngAfterViewInit() {
this.children.forEach((child: StepComponent, i: number) => {
this.subscriptions.add(
child.animate.subscribe(() => {
this.setStep(i);
})
);
});
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
setStep(index: number) {
this.step = index;
console.log(this.step);
}
nextStep() {
this.step++;
console.log(this.step);
}
prevStep() {
this.step--;
console.log(this.step);
}
}
请注意 children
订阅。
然后我创建了一个步骤组件
<mat-expansion-panel [expanded]="expanded"
(click)="animateMe()">
<mat-expansion-panel-header>
<mat-panel-title>
{{name}}
</mat-panel-title>
</mat-expansion-panel-header>
<div>
<ng-content>
</ng-content>
</div>
</mat-expansion-panel>
这是我想隐藏手风琴步骤的复杂性的地方。目前它是基本的,但请耐心等待。
然后我的代码如下所示:
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
@Component({
selector: "app-step",
templateUrl: "./step.component.html",
styleUrls: ["./step.component.scss"]
})
export class StepComponent implements OnInit {
@Input() name: string;
@Input() expanded: boolean;
@Output() animate: EventEmitter<void> = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
animateMe() {
console.log("clicked");
this.animate.emit();
}
}
注意 Output
事件。
所以,在我的组件中,我现在有这个:
<app-stepper #stepper>
<app-step name="Hall"
*ngIf="hall"
[expanded]="stepper.step === 0">
<!-- emitted for brevity -->
<button mat-raised-button
type="button"
color="primary"
(click)="stepper.nextStep()">Next</button>
</app-step>
<app-step name="Video"
[expanded]="stepper.step === 1">
<!-- emitted for brevity -->
</form>
</app-step>
</app-stepper>
当我按下下一步按钮时,它确实展开了 "step"。但是,如果我单击任何 headers,尽管我确实看到了控制台日志(因此事件发射器实际上正在发出),但未捕获订阅,因此 "step" 未重置。
有谁知道为什么我的代码:
this.children.forEach((child: StepComponent, i: number) => {
this.subscriptions.add(
child.animate.subscribe(() => {
this.setStep(i);
})
);
});
是不是被抓了?
我创建了一个 stackblitz,因为这似乎是一个有趣的问题。
如果我对问题的理解正确,我认为这实际上是一个#simple 修复。
我已将点击事件从步骤组件中的 mat-expansion-panel
移动到 mat-expansion-header
。
<mat-expansion-panel [expanded]="expanded">
<mat-expansion-panel-header (click)="animateMe()">
</mat-expansion-panel-header>
</mat-expansion-panel>
如您所说,订阅正在触发,但随后点击处理程序覆盖了对 nextStep
的调用,导致其重置。
基于这个问题的简单性,我假设我误解了问题?
我正在尝试通过制作我自己的版本来简化 angular material 手风琴,该版本试图稍微简化它。 我有一个 步进器组件:
<mat-accordion>
<ng-content>
</ng-content>
</mat-accordion>
这个很简单,有这些方法:
import {
Component,
AfterViewInit,
QueryList,
ContentChildren,
OnDestroy,
Input
} from "@angular/core";
import { StepComponent } from "./step.component";
import { Subscription } from "rxjs";
@Component({
selector: "app-stepper",
templateUrl: "./stepper.component.html",
styleUrls: ["./stepper.component.scss"]
})
export class StepperComponent implements AfterViewInit, OnDestroy {
@Input() closeOthers: boolean = true;
@ContentChildren(StepComponent) children: QueryList<any>;
step = 0;
private subscriptions: Subscription = new Subscription();
constructor() {}
ngAfterViewInit() {
this.children.forEach((child: StepComponent, i: number) => {
this.subscriptions.add(
child.animate.subscribe(() => {
this.setStep(i);
})
);
});
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
setStep(index: number) {
this.step = index;
console.log(this.step);
}
nextStep() {
this.step++;
console.log(this.step);
}
prevStep() {
this.step--;
console.log(this.step);
}
}
请注意 children
订阅。
然后我创建了一个步骤组件
<mat-expansion-panel [expanded]="expanded"
(click)="animateMe()">
<mat-expansion-panel-header>
<mat-panel-title>
{{name}}
</mat-panel-title>
</mat-expansion-panel-header>
<div>
<ng-content>
</ng-content>
</div>
</mat-expansion-panel>
这是我想隐藏手风琴步骤的复杂性的地方。目前它是基本的,但请耐心等待。 然后我的代码如下所示:
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
@Component({
selector: "app-step",
templateUrl: "./step.component.html",
styleUrls: ["./step.component.scss"]
})
export class StepComponent implements OnInit {
@Input() name: string;
@Input() expanded: boolean;
@Output() animate: EventEmitter<void> = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
animateMe() {
console.log("clicked");
this.animate.emit();
}
}
注意 Output
事件。
所以,在我的组件中,我现在有这个:
<app-stepper #stepper>
<app-step name="Hall"
*ngIf="hall"
[expanded]="stepper.step === 0">
<!-- emitted for brevity -->
<button mat-raised-button
type="button"
color="primary"
(click)="stepper.nextStep()">Next</button>
</app-step>
<app-step name="Video"
[expanded]="stepper.step === 1">
<!-- emitted for brevity -->
</form>
</app-step>
</app-stepper>
当我按下下一步按钮时,它确实展开了 "step"。但是,如果我单击任何 headers,尽管我确实看到了控制台日志(因此事件发射器实际上正在发出),但未捕获订阅,因此 "step" 未重置。
有谁知道为什么我的代码:
this.children.forEach((child: StepComponent, i: number) => {
this.subscriptions.add(
child.animate.subscribe(() => {
this.setStep(i);
})
);
});
是不是被抓了?
我创建了一个 stackblitz,因为这似乎是一个有趣的问题。
如果我对问题的理解正确,我认为这实际上是一个#simple 修复。
我已将点击事件从步骤组件中的 mat-expansion-panel
移动到 mat-expansion-header
。
<mat-expansion-panel [expanded]="expanded">
<mat-expansion-panel-header (click)="animateMe()">
</mat-expansion-panel-header>
</mat-expansion-panel>
如您所说,订阅正在触发,但随后点击处理程序覆盖了对 nextStep
的调用,导致其重置。
基于这个问题的简单性,我假设我误解了问题?