【问题标题】:Bindings not working in dynamically loaded component绑定在动态加载的组件中不起作用
【发布时间】:2016-03-20 23:51:44
【问题描述】:

我遇到了一个问题,如果我动态加载一个组件,模板中的任何绑定都不适合我。除此之外,ngOnInit 方法永远不会被触发。

loadView() {
    this._dcl.loadAsRoot(Injected, null, this._injector).then(component => {
      console.info('Component loaded');
    })
  }

动态加载的组件

import {Component, ElementRef, OnInit} from 'angular2/core'

declare var $:any

@Component({
    selector: 'tester',
    template: `
      <h1>Dynamically loaded component</h1>
        <span>{{title}}</span>
    `
})

export class Injected implements OnInit {

    public title:string = "Some text"

    constructor(){} 

    ngOnInit() {
      console.info('Injected onInit');
    }

}

这是我第一次使用动态加载的组件,所以我认为可能尝试不正确地实现它。

这里有一个plunkr 来演示这个问题。任何帮助将不胜感激。

【问题讨论】:

  • 有一个已知的issueloadAsRoot。你现在最安全的选择是使用loadNextToLocationloadIntoLocation
  • @EricMartinez 我要加载的组件是一个模态对话框。我试图从中加载它的组件位于具有fixed css 样式的元素内,因此该对话框几乎需要作为body 标记的第一个子项加载。我可以在深度嵌套的组件中使用loadNextToLocationloadIntoLocation 执行此操作吗?
  • 我认为你可以用纯 CSS 来解决这个问题。如果您将每个位置设置为 0(上、左、右、下)、固定位置和较高的 z-index 值,则无论加载到何处,您都可以拥有一个模态对话框。
  • @EricMartinez 我很欣赏这一点,但我真的不想因为这个错误而搞乱对我来说工作得很好的 CSS。我决定通过前向引用传递根AppComponent,现在使用loadIntoLocationAppComponentElementRef。感谢您的帮助。
  • 您可以添加您的解决方案作为答案,可能对其他人有所帮助

标签: javascript angular


【解决方案1】:

正如Eric Martinez 所指出的,这是一个与loadAsRoot 的使用相关的已知错误。建议的解决方法是使用loadNextToLocationloadIntoLocation

对我来说,这是有问题的,因为我试图动态加载的组件是来自具有fixed css 定位的组件内部的模态对话框。我还希望能够从任何组件加载模态并将其注入到 DOM 中的相同位置,而不管它是从哪个组件动态加载的。

我的解决方案是使用forwardRef 将我的根AppComponent 注入想要动态加载我的模态的组件中。

constructor (
    .........
    .........
    private _dcl: DynamicComponentLoader,
    private _injector: Injector,
    @Inject(forwardRef(() => AppComponent)) appComponent) {

    this.appComponent = appComponent;
}

在我的AppComponent 中,我有一个方法可以返回应用程序的ElementRef

@Component({
    selector: 'app',
    template: `
        <router-outlet></router-outlet>
        <div #modalContainer></div>
    `,
    directives: [RouterOutlet]
})

export class AppComponent {

    constructor(public el:ElementRef) {}

    getElementRef():ElementRef {
        return this.el;
    }

}

回到我的另一个组件(我想从中动态加载模式的那个)我现在可以调用:

this._dcl.loadIntoLocation(ModalComponent, this.appComponent.getElementRef(), 'modalContainer').then(component => {
    console.log('Component loaded')
})

也许这会帮助其他有类似问题的人。

【讨论】:

  • 当我尝试它时,loadIntoLocation 会将新组件附加到引用的标记下(在您的示例中,在modalContainer div 下。问题是,当我调用它两次时,组件将与以前创建的组件堆叠在一起(最新的组件在顶部)。我想要的是 loadAsRoot 行为,其中第二次调用将替换以前的组件。您是否在第二次调用 loadIntoLocation 之前手动清理 DOM?
  • 在哪里可以找到@Inject 文档?在 Angular 2 文档中尚不可用...
  • 子组件确实加载了,但动态加载组件的 ngOnInit 或 ngAfterViewInit 方法仅在我执行鼠标移动时才被调用。你们中有人遇到过这个问题吗?
【解决方案2】:

无需从 DOM 中清除组件实例。 使用 angular2/core 包中的 'componentRef' 来创建和处理组件实例。 使用 show() 将模态组件加载到所需位置,并使用 hide() 在第二次调用 loadIntoLocation 之前处理组件实例。

例如:

@Component({
  selector: 'app',
  template: `
    <router-outlet></router-outlet>
    <div #modalContainer></div>
 `,
  directives: [RouterOutlet]
})
export class AppComponent {
  private component:Promise<ComponentRef>;

  constructor(public el:ElementRef) {}

  getElementRef():ElementRef {
    return this.el;
  }

  show(){
    this.component = this._dcl.loadIntoLocation(ModalComponent,this.appComponent.getElementRef(), 'modalContainer').then(component => {console.log('Component loaded')})
  }

  hide(){
    this.component.then((componentRef:ComponentRef) => {
      componentRef.dispose();
      return componentRef;
    });
  }
}

【讨论】:

    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 2011-11-28
    • 1970-01-01
    相关资源
    最近更新 更多