【问题标题】:Why portal component is not rendering in template?为什么门户组件不在模板中呈现?
【发布时间】:2021-07-04 05:04:10
【问题描述】:

我使用Angular portal动态渲染组件。

组件在订阅中监听新的portal$组件:

ngOnInit() {
    this.portal$ = this.mapLibraryService.portalBridgeService.portal$;
    this.portal$.subscribe((e) => console.log(e));
}

那么模板有:

<ng-template [cdkPortalOutlet]="portal$ | async"></ng-template>

在控制台日志中,我得到了我尝试渲染的组件:

但它不会呈现,直到我不点击任何地方或调整窗口大小或在页面上执行任何操作。

如何调试和修复?

那是我改变portal$主题的地方:

editLayer(parameters: SearchParameters): Promise<any> {
    return this.showObjects(parameters).then((response) => {  
       this.portalBridgeService.set(this.portalBridgeService.portals.EDIT);
    });
}

这是 this.portalBridgeService.set(this.portalBridgeService.portals.EDIT); 我如何将数据发送到portal$.

如果要搬家:

this.portalBridgeService.set(this.portalBridgeService.portals.EDIT);upper from promise 它工作正常。

重要事项:

如果要在订阅中进行此操作:

    this.portal$ = this.mapLibraryService.portalBridgeService.portal$;
    this.portal$.subscribe((e) => {

         setTimeout(() => cdr.detectChanges())

});

它开始工作,它呈现组件,到那时,如果发生变化,就不会再出现了。

我尝试了另一种方式,在根组件中我有:

export class AppComponent implements OnInit, OnDestroy {

       public action: any;
       ngOnInit() {
          this.mapLibrary.portalBridgeService.portal$.subscribe((e) => {
            if (e.type === 'Map') {
                this.action = EditMapWrapperComponentComponent;
            }
        });
       }
}

模板是:

<ng-container *ngComponentOutlet="action"></ng-container>

服务:

export class PortalBridgeService {
    private portalSubject = new ReplaySubject<Portal>();
    public portal$ = this.portalSubject.asObservable();

    public set(portal: Portal) { 
                   this.portalSubject.next(portal);
    }

}

我有同样的问题,我收到消息,但 Angular 不会在组件 AppComponent 中呈现它,直到我调整页面大小或随时单击。

这是我的simplified example

【问题讨论】:

标签: angular


【解决方案1】:
     this.portalBridgeService.set(this.reonMap.portalBridgeService.portals.EDIT);

如果不发布整个代码,很难以 100% 的信心回答,但根据您在此处提供的内容,我怀疑您保留了一个服务字段,当更改时您希望影响您的组件。

您必须知道默认检测策略会观察当前组件的字段并呈现在这些字段上检测到的任何更改。因此,如果您更改服务上的类字段,则不会从您当前的组件中检测到它。

如果是这种情况,请考虑在组件上保留一个您希望在更改时呈现的字段。

编辑: 修改了您发布的示例以执行您需要执行的操作

我简化了我的代码并在此处发布,而不是门户 CDK 我推送字符串 多变的。 stackblitz.com/edit/angular-ivy-dkkwpc 结果我需要 查看渲染组件

full-map.component.ts

export class FullMapComponent implements OnInit {
  portal$: Observable<string>;
  shouldShow: boolean;

  constructor(private mapLibrary: MapLibrary) {}

  ngOnInit() {
    this.portal$ = this.mapLibrary.reonMap.portal.portal$;
    this.portal$.subscribe((portal: string) => {
      console.log(portal);
      if (portal === 'simple') {
        this.shouldShow = true;
      } else {
        this.shouldShow = false;
      }
    });
  }

  render() {
    this.mapLibrary.reonMap.portal.set('simple');
  }
}

full-map.component.html

<div *ngIf="(portal$ | async) == 'full'">
  <app-render></app-render>
</div>

<div *ngIf="shouldShow">
  <app-render></app-render>
</div>

<div (click)="render()">Render component 2</div>

现在当你点击 app-renderer 组件时就会出现。

即使在 ngOnInit 期间,您也必须订阅它,以确保您及时收到响应。您所做的是在点击完成后订阅,这已经很晚了。

【讨论】:

  • 是的,在组件中,我只监听 portal$ 更改的服务的更改。但是我不能将此字段存储在组件中,因为门户是动态创建的。如何在组件中设置并更改?我不相信 Angulat 没有检测到注入组件的服务的变化。
  • 我添加了一些细节
  • 我简化了我的代码并发布在这里,而不是门户 CDK 我推送字符串变量。 stackblitz.com/edit/angular-ivy-dkkwpc 结果我需要看到渲染的&lt;app-render&gt;&lt;/app-render&gt; 组件
  • @MeganClerc 检查我的更新答案,您之前的评论将起作用
  • 当你点击它时它会起作用,但是当你在外面设置主题门户$时,例如几秒钟后的 id 代码 (setTimout) 它不起作用。我们可以开始聊天吗?
猜你喜欢
  • 2013-06-21
  • 1970-01-01
  • 2017-06-10
  • 1970-01-01
  • 2019-04-09
  • 2017-10-06
  • 2018-04-21
  • 2011-11-25
  • 1970-01-01
相关资源
最近更新 更多