Angular中用于订阅和接收不相关组件之间更改的声明性方法?

huangapple go评论64阅读模式
英文:

Declarative approach for subscribing to and receiving changes between unrelated components in Angular?

问题

  • 我有一个仪表板(父组件),其中包含侧边栏和导航栏(子组件)。
  • 在侧边栏上,我应用了自定义权限指令,用于检查范围是否有权限查看。
  • 在导航栏上,我有一个包含管理员、经理和员工角色选项的菜单,当用户更改角色时,
  • 我希望根据更改的角色权限来更改侧边栏链接。

我尝试将可观察对象传递给侧边栏

scope$: Observable<Roles> = this.scopeService.scope$;

使用异步管道

<app-sidebar [scope]="scope$ | async"></app-sidebar>

并在 ngOnInit 中进行订阅

ngOnInit(): void {
    this.scopeService.scope$.subscribe();
}

但它不起作用。

我看到了一些使用事件发射器的帖子,但我真的想使用声明性模式。

这里是更详细的 stackblitz 链接。

英文:

Problem statement:

  • I have a Dashboard (parent component) which have Sidebar & Navbar (child component).
  • In Sidebar, on links I have custom permission directive applied which checks whether the scope have permission to view or not.
  • In Navbar, I have a menu with Admin, Manager & staff roles options & when user changes the roles
  • I want to change the sidebar links based on that changed scope permissions.

I tried passing observable to sidebar

scope$: Observable&lt;Roles&gt; = this.scopeService.scope$;

using aysnc pipe

&lt;app-sidebar [scope]=&quot;scope$ | async&quot;&gt;&lt;/app-sidebar&gt;

& subscribing in ngOnInit

ngOnInit(): void {
    this.scopeService.scope$.subscribe();
  }

but it doesn't work.

I have seen post which use the event emitter but I really want to use declarative pattern.

Here is the stackblitz link for more brief.

答案1

得分: 0

That's not how async pipe works. Async pipe automatically subscribes to observable and gets its value. In your case, you don't want to do it; you just want to pass an observable. You don't need async pipe for that; just do this:

<app-sidebar [scope$]="scope$"></app-sidebar>

And now in app-sidebar:

@Input
scope$: Observable<Roles> = this.scopeService.scope$;

ngOnInit(): void {
    this.scope$.subscribe();
}

EDIT:

After checking your stackblitz, I see where your problem is. In your has-permission directive, you use a snapshot of scope instead of subscribing to it. You should do this:

ngOnInit(): void {
    this.scopeService.scope$.subscribe((newScope) => {
        this.scope = newScope;
        this.checkPermissions();
    });
}

This way, every time the scope changes, the checkPermissions() method is called. You still need to fix how you show your elements because there are some issues with it. It seems that you're not clearing options that the scope already had permissions for, and you create a new one, making it duplicate. You could fix it by making showElement like this:

showElement(canShow: boolean): void {
    this.viewContainer.clear();
    if (canShow) {
        this.viewContainer.createEmbeddedView(this.templateRef);
    }
}
英文:

That's not how async pipe works. Async pipe automatically subscribes to observable, and gets its value. In your case you don't want to do it, you just want to pass observable. You don't need async pipe for that, just do this:

&lt;app-sidebar [scope$]=&quot;scope$&quot;&gt;&lt;/app-sidebar&gt;

and now in app-sidebar:

@Input
scope$: Observable&lt;Roles&gt; = this.scopeService.scope$;

ngOnInit(): void {
    this.scope$.subscribe();
  }

EDIT:

After checking your stackblitz I see where your problem is. In your has-permission directive you use snapshot of scope instead of subscribing to it. You should do this:

  ngOnInit(): void {
    this.scopeService.scope$.subscribe((newScope) =&gt; {
      this.scope = newScope;
      this.checkPermissions();
    });
  }

This way, every time scope changes, checkPermissions() method is called. You still need to fix how you show your elements, because there are some issues with it. Seems that you're not clearing options that scole already had permissions for, and you create a new one, making it duplicate. YOu could fix it with making showElement like this:

  showElement(canShow: boolean): void {
    this.viewContainer.clear();
    if (canShow) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }

huangapple
  • 本文由 发表于 2023年5月25日 17:34:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76330834.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定