【问题标题】:How to target specific element with DynamicComponentLoader?如何使用动态组件加载器定位特定元素?
【发布时间】:2016-01-16 02:29:07
【问题描述】:

背景

我有一个代表文件夹列表和文档类别的数据;我通过网络界面从我们的信息管理软件中获取它。从每个项目都有ParentFolderNo 的原始列表中,我创建了一个具有children: any[] 属性的对象-基本上现在我有嵌套的项目列表;像这样:

{
  id: 123,
  Guid: "8dcaae38-4dcc-48f7-bd91-c8b0cb725890"
  children: [
    {
      id: 234,
      Guid: "...."
    },
    {
      id: 345,
      Guid: "...."
      children: [...]
    }
  ]
}

实施

那里有更多的对象,有些有自己的孩子,有些没有,但每一个都是独一无二的,并且有一个独特的Guid。我需要从这个对象创建 UI 元素,让用户选择特定的文件夹或类别并限制搜索。您可以将其视为可选择的面包屑。我创建了使用DynamicComponentLoader 来显示此数据的特定“树”的组件:

@Component({
  host: { "[attr.id]": "category.Guid" },
  selector: 'category-group',
  template: `
    <ul class="category__group">
      <li>
        <a (click)="select()">All Categories</a>
      </li>
      <li [class.selected]="child.selected" *ngFor="#child of category.children">
        <a *ngIf="!child.selected" (click)="select(child)">{{ child.Name }}</a>
        <b *ngIf="child.selected">{{ child.Name }}</b>
      </li>
    </ul>
  `,
})
class Category {
  public category: any;

  select(theCategory: any) {
    this.category.children.map(subcategory => subcategory.selected = false);
    if (theCategory) {
      theCategory.selected = true;
      // pass theCategory to CategorySelectComponent
      // to create new category-group... this works.
    }
  }
}

@Component({
  selector: 'category-select',
  template: `
    <b>Root</b> 
    <div #root></div>
  `,
})
export class CategorySelectComponent {
  @Input() root: any;

  constructor(
    private _dcl: DynamicComponentLoader, 
    private _eref: ElementRef, 
    private _inj: Injector
  ) {}

  ngOnInit() { this.create(this.root); }

  create(parent: any) {
    if (!parent.children) return;
    this._dcl
      .loadIntoLocation(Category, this._eref, 'root')
      .then(ref => ref.instance.category = parent)
  }
}

这可行,但有一个缺陷 - 它只是添加了新的&lt;category-group&gt;。当我选择不同的孩子时,我需要替换“下方”的类别组。所以:

有没有办法用 DynamicComponentLoader 替换组件?

  create(parent: any) {
    if (!parent.children) return;
    // Guid":"8dcaae38-4dcc-48f7-bd91-c8b0cb725890"
    this._dcl
      .loadIntoLocation(Category, this._eref, 'root')
      .then(ref => ref.instance.category = parent)
  }

我可以用这个create() 函数做什么来获得我需要的功能?如何在_dcl 中使用带有id="8dcaae38-4dcc-48f7-bd91-c8b0cb725890" 的元素?我试过other methods,但没能成功...

谢谢。

【问题讨论】:

  • 为什么不删除现有的并添加新的?到目前为止,您的工作方法是否有 plnkr?
  • 还没有 plunkr,没有时间隔离这个,太多的依赖项(;至于删除...我还没有尝试。在 DOM 中,当我使用 loadIntoLocation() 时,它们是兄弟姐妹,还不确定我是否应该直接从 DOM 中删除它们,当我生成要搜索的类别列表时可能会产生副作用......没有那么远(;
  • 现在我想,删除现有的可能是正确的方法。我可以通过selected 属性过滤列表...

标签: angular


【解决方案1】:

我实际上遇到了同样的问题(我是 Angular2 的新手),但基本上如果您使用 loadIntoLocation() 方法,它不会替换任何现有模板。但是如果你使用loadAsRoot() 它会(考虑到你指向同一个选择器。例如:

this._dynamicComponentLoader.loadAsRoot(ComponentA, '#container', this._injector)
                .then((res) => {
                    res.instance["label"] = "text1";
                    compRef.location.internalElement.parentView.changeDetector.ref.detectChanges();
                });

而下次你想将 ComponentA 的内容替换为其他模板(假设是原始的,ComponentB)时:

this._dynamicComponentLoader.loadAsRoot(ComponentB, '#container', this._injector)
                .then((res) => {
                    res.instance["label"] = "text2";
                    compRef.location.internalElement.parentView.changeDetector.ref.detectChanges();
                });

你看这里有一条奇怪的线:

compRef.location.internalElement.parentView.changeDetector.ref.detectChanges();

如果您想通知组件在使用loadAsRoot() 方法时监听其属性的变化,则需要该行,如下所示:

https://github.com/angular/angular/issues/6223#issuecomment-193895253

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2014-03-31
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    相关资源
    最近更新 更多