Angular (v5+) - Snackbar “openFromComponent”,组件通信
Posted
技术标签:
【中文标题】Angular (v5+) - Snackbar “openFromComponent”,组件通信【英文标题】:Angular (v5+) - Snackbar "openFromComponent", component communication 【发布时间】:2018-10-29 03:58:59 【问题描述】:Angular (v5.2.10) Snackbar
--|简介 |--
我有一个 Angular 组件(我们称之为“父级”)初始化一个名为 snackBar
的 Angular 材质 Snackbar。传入的是 SnackbarMessage
,这是另一个带有包含小吃栏标记的模板的组件。在这种情况下使用snackBar.openFromComponent(SnackBarMessage)
是必要的,因为我需要在小吃栏中使用的不仅仅是纯文本[如标记、点击事件等],而snackBar.open(message, action)
是不够的。
--|代码 |--“父”组件:
@Component(
selector: 'app-parent',
templateUrl: './parent.component.html'
)
export class Parent implements AfterViewInit
public constructor(public snackBar: MatSnackBar)
public ngAfterViewInit(): void
this.snackBar.openFromComponent(SnackbarMessage);
public dismissSnackbar(): void
this.snackBar.dismiss();
“SnackbarMessage”组件:
@Component(
selector: 'app-snackbar-message',
templateUrl: './snackbar-message.html'
)
export class SnackbarMessage
“snackbar-message.html”标记:
<p>(Snackbar message)</p>
<button type="button" (click)="dismissSnackbar();">Dismiss</button>
--|问题 |--
在导入的SnackbarMessage
模板(snackbar-message.html)中我需要调用Parent 组件的dismissSnackbar();
,我们如何使用这个Angular 应用程序的当前封装来做到这一点?
【问题讨论】:
【参考方案1】:您实际上不需要调用父组件的“dismissSnackbar()”方法来关闭snackbar。您可以简单地将“MatSnackBar”注入“SnackbarMessage”组件并在“MatSnackBar”的注入实例上调用“dismiss()”方法。正如docs 中所写,这将隐藏当前可见的 Snackbar,即在您的示例中使用“SnackbarMessage”组件打开的 Snackbar。以下是您更新的“SnackbarMessage”组件:-
“SnackbarMessage”组件:
@Component(
selector: 'app-snackbar-message',
templateUrl: './snackbar-message.html'
)
export class SnackbarMessage
constructor(public snackBar: MatSnackBar)
public dismissSnackbar(): void
this.snackBar.dismiss();
【讨论】:
这不是太复杂+1 如果您需要使用 MatSnackBarRef 中的方法,例如dismissWithAction(),你也可以注入它。private matSnackBar: MatSnackBarRef<MatSnackBar>
.【参考方案2】:
yatharth 的解决方案会奏效。
但是,如果您想让您的组件经得起未来的考验,您应该使用服务。借助服务,您可以从应用程序中的任何位置关闭您的小吃店——而不仅仅是像他的方法中的小吃店消息组件。
创建一个可观察的流,并在您的快餐栏组件中订阅它。它只会传递一个布尔值(true 或 false),每次在流中发出新值时,您都可以使用该值切换您的快餐栏组件。
简单示例:
@Injectable()
export class SnackbarService
status: BehaviorSubject<boolean> = new BehaviorSubject(false);
status$: Observable<boolean> = this.status.asObservable();
@Component(
selector: 'app-snackbar-message',
templateUrl: './snackbar-message.html'
)
export class SnackbarMessage
open: boolean = false;
constructor(public snackbarService: SnackbarService)
snackbarService.status$.subscribe((open: boolean) => this.open = open);
现在,您只需在应用中的任何位置打开快餐栏即可:
snackbarService.status.next(true);
或者这样关闭snackbar:
snackbarService.status.next(false);
如果您想获得更多的案例,而不仅仅是打开/关闭,您可以使用具有不同值的枚举:
export enum SnackbarStatus
Open,
Closed,
SomethingElse
在您的可观察流中传递一个枚举,而不是布尔值:
@Injectable()
export class SnackbarService
status: BehaviorSubject<SnackbarStatus> = new BehaviorSubject(SnackbarStatus.Closed);
status$: Observable<SnackbarStatus> = this.status.asObservable();
【讨论】:
很好的解释,这个解决方案可以很好地满足我的需要。谢谢你好先生【参考方案3】:我今天使用MatSnackBar.openFromTemplate
而不是MatSnackBar.openFromComponent
解决了与您类似的问题。使用这种方法,子组件的所有功能都可以直接从父组件访问。
“父组件”充当MatSnackBar
和SnackBarMessageComponent
之间的“中介”类。现在,SnackBarMessageComponent
与 MatSnackBar 解耦,成为一个普通组件,可以重命名为 MessageComponent
。您可以使用普通的@Input
和@Output
在父组件和子组件之间发送和接收数据。您可以根据需要添加任意数量的@Input
s 或@Output
s。
代码超过 1000 个单词:
parent.component.html
<h1>parent component</h1>
<ng-template #snackBarTemplate>
<app-message [msg]="message" (onDismissClick)="dismissSnackbar"></app-message>
</ng-template>
parent.component.ts
@Component(
selector: 'app-parent',
templateUrl: './parent.component.html'
)
export class Parent implements AfterViewInit
@ViewChild('snackBarTemplate')
snackBarTemplate: TemplateRef<any>;
public message: string;
public constructor(public snackBar: MatSnackBar)
public ngAfterViewInit(): void
this.message = '(Snackbar message)';
this.snackBar.openFromTemplate(snackBarTemplate);
public dismissSnackbar(): void
this.snackBar.dismiss();
message.component.ts
@Component(
selector: 'app-message',
templateUrl: './message.html'
)
export class MessageComponent
@Input()
msg: string;
@Output()
onDismissClick= new EventEmitter<any>();
dismissClicked()
this.onDismissClick.emit(null);
message.component.html
<p>msg</p>
<button type="button" (click)="dismissClicked()">Dismiss</button>
(以上代码未经测试)
【讨论】:
【参考方案4】:使用 ComponentRef 来调用你的方法。
MyCustomSnackBarComponent 使用您的自定义方法
public miMethod(): void
console.log('call from parent');
您在其中创建了 MyCustomSnackBarComponent 实例的组件:
const snackBarRef = this.snackbar.openFromComponent(MyCustomSnackBarComponent);
snackBarRef.instance.miMethod();
如果您的方法有参数,此解决方案仍然适用
【讨论】:
以上是关于Angular (v5+) - Snackbar “openFromComponent”,组件通信的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 5 的 Angular 材质 Snackbar 中添加图标
Angular2 Material SnackBar 集成问题
Angular 材质 Snackbar 配置与自定义 panelClass 配置,用于错误、成功、警告消息