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

时间:2018-05-18 16:45:18

标签: angular typescript angular-components snackbar

Angular(v5.2.10)Snackbar

- |简介| -
我有一个Angular组件(我们称之为“Parent”)初始化一个名为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应用程序的当前封装来做到这一点?

4 个答案:

答案 0 :(得分:6)

您实际上不需要调用父组件的“dismissSnackbar()”方法来关闭快餐栏。您可以简单地将“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 :(得分:3)

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

“父组件”在MatSnackBarSnackBarMessageComponent之间充当“调解人”类。现在,SnackBarMessageComponent与MatSnackBar分离,成为一个普通的组件,可以重命名为MessageComponent。您可以使用普通的@Input@Output在父级和子级组件之间发送和接收数据。您可以根据需要添加任意数量的@Input@Output

代码说了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>

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

答案 2 :(得分: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);

或关闭小吃店:

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 :(得分:0)

使用ComponentRef调用您的方法。

MyCustomSnackBarComponent 和您的自定义方法

public miMethod(): void { 
    console.log('call from parent');
}

在其中创建 MyCustomSnackBarComponent 实例的组件:

const snackBarRef = this.snackbar.openFromComponent(MyCustomSnackBarComponent);
snackBarRef.instance.miMethod();

如果您的方法有参数,此解决方案仍然适用