【问题标题】:How to render a part of Component A in Component B如何在组件 B 中渲染组件 A 的一部分
【发布时间】:2018-06-30 17:27:52
【问题描述】:

我有一个组件 AB

<div class="A">
    <div class="A1"></div>
    <div class="A2"></div>
</div>

<div class="B">
    <!--want to display <div class="A1"></div> here-->
</div>

组件 B 不包含组件 A 或其他方式

<componentA></componentA>
<componentB></componentB>

我尝试将 &lt;div class="A1"&gt;&lt;/div&gt; 包装到 ng-template 中,然后在 componentB 中进行查询,但它始终是 undefined

@ViewChild('templ') templ: TemplateRef&lt;any&gt;;

然后我意识到@ViewChild是查询子组件,那么&lt;ng-template&gt;不是子组件怎么查询和渲染呢?

【问题讨论】:

    标签: angular ng-template ng-content


    【解决方案1】:

    看看 Alex Rickabaugh 的 awesome sideNav sample,它演示了您所需要的。

    基于此,您需要在您的ComponentA 中定义一个ng-container。然后你需要用自定义指令标记你的ComponentB,并且有一个连接ComponentAComponentB的服务:

    <div class="A1"><div>
    <div class="A2" *leftNav >
      <h3>Content</h3>
    </div>
    

    指令:

    @Directive({
      selector: '[leftNav]',
    })
    export class LeftNavDirective implements OnInit {
      constructor(private leftNav: LeftNav, private ref: TemplateRef<any>) {}
    
      ngOnInit(): void {
        this.leftNav.setContents(this.ref);
      }
    }
    

    服务:

    @Injectable()
    export class LeftNav {
      private _state = new BehaviorSubject<TemplateRef<any>|null>(null);
      readonly contents = this._state.asObservable();
    
      setContents(ref: TemplateRef<any>): void {
        this._state.next(ref);
      }
    
      clearContents(): void {
        this._state.next(null);
      }
    }
    

    最后,在您的ComponentB 中,您必须在ngAfterViewInit 上订阅您的&lt;div class="A1"&gt; ... &lt;div&gt;

    ngAfterViewInit(): void {
        this
          .leftNav
          .contents
          .subscribe(ref => {
            if (this._current !== null) {
              this._current.destroy();
              this._current = null;
            }
            if (ref === null) {
              return;
            }
            this._current = this.vcr.createEmbeddedView(ref);
        });
      }
    

    P.S 有关于该主题的 videoslides

    【讨论】:

      【解决方案2】:

      您可以在父组件中创建公共ng-template,并将其templateRef 传递给组件的Input 绑定中的子组件。稍后内部组件将填充该模板的模板绑定。

      这意味着在两个组件中添加@Input a1: TemplateRef&lt;any&gt;;,并在组件A和B的父组件的父组件中放置ng-template下方(基本上它们具有相同的父组件)。

      <ng-template #a1>
          <div class="A1">
             {{item.Description}}
          </div>
      </ng-tmeplate>
      

      组件 A 模板

      <div class="A">
          <ng-container 
             *ngTemplateOutlet="a1;context:{item: valueFromComponentA}">
          </ng-container>
          <div class="A2"></div>
      </div>
      

      组件 B 模板

      <div class="B">
          <ng-container 
             *ngTemplateOutlet="a1;context:{item: valueFromComponentB}">
          </ng-container>
      </div>
      

      【讨论】:

        【解决方案3】:

        将组件A的模板渲染为组件B的内容

        <ComponentB>
           <ComponentA></ComponentA>
        </ComponentB>
        

        componentB 的内部模板渲染“内容”(在本例中为 ComponentA 的模板)

        ComponentB.component.html

        <ng-content> </ng-content>
        

        要访问在ComponentB 中呈现的ComponentA,请使用ContentChild

        @ContentChild(ComponentA) footer: componentA;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-27
          • 1970-01-01
          • 2011-09-03
          • 1970-01-01
          • 2021-06-30
          • 1970-01-01
          • 2013-01-20
          • 1970-01-01
          相关资源
          最近更新 更多