Angular(v5 +)-Snackbar“ openFromComponent”,组件通信

Cod*_*ene 2 typescript snackbar angular-components angular

角(v5.2.10)小吃吧

-| 简介|-
我有一个Angular组件(我们称之为“父母”),它初始化了一个名为的Angular材质Snackbar snackBarSnackbarMessage传入的是,另一个组件的模板包含快餐栏标记。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();
  }
}
Run Code Online (Sandbox Code Playgroud)

“ SnackbarMessage”组件:

@Component({
  selector: 'app-snackbar-message',
  templateUrl: './snackbar-message.html'
})
export class SnackbarMessage { }
Run Code Online (Sandbox Code Playgroud)

“ snackbar-message.html”标记:

<p>(Snackbar message)</p>
<button type="button" (click)="dismissSnackbar();">Dismiss</button>
Run Code Online (Sandbox Code Playgroud)


-| 问题|-
在导入的SnackbarMessage模板(snackbar-message.html)中,我需要调用Parent组件的dismissSnackbar();,我们如何使用此Angular应用程序的当前封装来做到这一点?

yat*_*ney 9

您实际上不需要调用父组件的“ dismissSnackbar()”方法来关闭小吃栏。您可以简单地将“ MatSnackBar”注入到“ SnackbarMessage”组件中,并在该注入的“ MatSnackBar”实例上调用“ dismiss()”方法。如文档中所述,这将隐藏当前可见的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很棒的一次性解决方案!已投票 (2认同)

Lan*_*ara 6

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在从你的应用程序的任何地方,你所要做的就是打开小吃店:

snackbarService.status.next(true);
Run Code Online (Sandbox Code Playgroud)

或者这样关闭小吃店:

snackbarService.status.next(false);
Run Code Online (Sandbox Code Playgroud)

如果您想获得更多案例,而不仅仅是打开/关闭,您可以使用具有不同值的枚举:

export enum SnackbarStatus {
    Open,
    Closed,
    SomethingElse
}
Run Code Online (Sandbox Code Playgroud)

在可观察流中传递枚举,而不是布尔值:

@Injectable()
export class SnackbarService {
    status: BehaviorSubject<SnackbarStatus> = new BehaviorSubject(SnackbarStatus.Closed);
    status$: Observable<SnackbarStatus> = this.status.asObservable();
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*edo 5

我今天用MatSnackBar.openFromTemplate代替来解决了一个类似于您的问题MatSnackBar.openFromComponent。通过这种方法,子组件的所有功能都可以直接从父组件访问。

的“父组件”充当之间的“中介”类MatSnackBarSnackBarMessageComponent。现在,将SnackBarMessageComponentMatSnackBar解耦,并成为一个普通组件,可以将其重命名为MessageComponent。您可以使用plain @Input和在父组件和子组件之间发送和接收数据@Output。您可以添加尽可能多的@InputS或@Output只要你想秒。

该代码说了超过1.000个字:

parent.component.html

<h1>parent component</h1>
<ng-template #snackBarTemplate>
    <app-message [msg]="message" (onDismissClick)="dismissSnackbar"></app-message>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

message.component.html

<p>{{msg}}</p>
<button type="button" (click)="dismissClicked()">Dismiss</button>
Run Code Online (Sandbox Code Playgroud)

(以上代码尚未经过测试)