【问题标题】:How to load dynamic HTML into DIV with component? Angular5如何使用组件将动态 HTML 加载到 DIV 中?角5
【发布时间】:2018-06-17 15:41:39
【问题描述】:

这两天我一直在努力寻找解决这个问题的方法。不幸的是,我无法得到我想要的。我正在使用 Angular5。

<div class="form-group col-md-12" [innerHTML]="GetItemsOfHolder(item.children[1],1,
'UserConfigGroupsLabelHolder') | keepHtml"></div>

这是我的函数的样子:

GetItemsOfHolder(item: any,divName:string, recursive: boolean = false,typeName:string="") 
{
return html;
}

一切正常,除非我返回的 html 包含一个名为 Select2 的包 这是我用来将 html 添加到这个 div 中的,它工作得很好。直到我想添加动态包。

我的意思是返回 html 包含这样的包组件:

itemhtml +="<select2 data-type='"+holderItem.itemType+"' 
[data]='this.dropdownData."+holderItem.name+"'></select2>"  

这只是将纯文本返回给浏览器,并没有按预期工作。

我想要的是将字符串转换为组件或任何其他可以工作并生成 select2 下拉列表的方式。

我一直在尝试搜索很多东西。但它不起作用 This is good but I can not understand this 不推荐使用动态组件加载。

谁能给我一个想法我该如何解决这个问题?任何例子都会很棒。

【问题讨论】:

  • Angular 会清理几乎所有内容,这就是为什么你会得到纯文本。您要研究的是 ReflectiveInjector,主要是 ComponentFactoryResolver。主要思想是组件需要渲染一些其他信息(服务、其他组件等),因此您使用注入器获取依赖注入引用,然后组件工厂构建您的组件。然后将其插入到 ViewChild 引用中。有一种更复杂的方式来动态制作组件,它使用编译器并需要 ModuleWithComponentFactories,这就是 Angular 实际使用的方式。
  • @Devcon 谢谢你的回答,你能给我举个例子吗?
  • @Justcode 这不是你妈妈的 AngularJS ;D 开个玩笑,你不能像在 AngularJS 中那样添加新组件 观看和哭泣youtube.com/…
  • @user1740331 在 1.0 之前我能够轻松做到这一点:P 任何方式感谢链接。
  • 你可以用angular.io/guide/dynamic-component-loader做到这一点

标签: javascript angular typescript dynamic components


【解决方案1】:

正如@Devcon 评论的那样

Angular 会清理几乎所有的东西,所以这就是你的原因 获取纯文本。您要查看的是 ReflectiveInjector 主要是ComponentFactoryResolver。主要思想是组件 需要渲染一些其他信息(服务、其他组件等), 所以你使用 Injector 来获取依赖注入 refs 然后 组件工厂构建您的组件。然后将其插入到 ViewChild 参考。还有一种更复杂的动态方式 制作使用编译器并需要 ModuleWithComponentFactories,这是 Angular 实际使用的。

搜索角度,我接受角度不应该以这种方式完成。

因为我必须创建必须以 html 呈现的完全动态页面。我稍微改变了我的json并使用 ng-container and ng-template 并使用 ngswitch 我在它自己的模板中进行了递归调用,发现它工作得很好。

使用这个我有很多好处: HTML(我动态渲染)本身就是 HTML,代码干净易读,易于维护。

这里给出的示例与我所做的几乎相同。 https://stackoverflow.com/a/40530244/2630817

这里有一个小例子:

<ng-template #itemsList let-itemsList>
  <div *ngFor="let item of itemsList;let i = index">
    <div [ngSwitch]="item.itemType">
        <div class="form-group" *ngSwitchCase="'TEXT'">
            <label>
                {{item.label}}
              </label>
              <input id="{{item.name}}" value="{{item.value}}" type='text' class='form-control txtbox ui-autocomplete-input'/>
        </div>
        <div class="form-group" *ngSwitchCase="'PASSWORD'">
            <label>
                {{item.label}}
              </label>
              <input id="{{item.name}}" value="{{item.value}}" type='password' class='form-control txtbox ui-autocomplete-input'/>
        </div>
        <div class="form-group" *ngSwitchCase="'BOOLEAN'">
            <label style='width:40%'>{{item.label}}</label>
            <div class="form-group"><input id="{{item.name}}" type='checkbox' /></div>

        </div>
        <div  class="form-group" *ngSwitchCase="'LABEL'">
            <label class="form-control">{{item.label}}</label>
        </div>
        <div class="form-group"  *ngSwitchDefault>
            <label>
                {{item.label}}
              </label>
              <select2 class="form-control"  [data]="GetDropDowndata(item.holderId)" [cssImport]="false" [width]="300" [options]="GetOptions(item.type)"></select2>
          </div>
    </div>
  </div>

【讨论】:

  • 能否请您提供有效的 stackblitz 演示。 ?我也在这个问题的中间。我正在尝试的是。我正在通过后端 GET 方法获取 html 模板。我需要在前端显示选择选项并输入文本。如果您分享演示,那将非常有帮助。谢谢
  • 我终于发现它不能用输入元素来完成,因为 Angular 会清理除块级和内联元素之外的几乎所有元素。
  • @worstCoder 太棒了。建议将 html 保存在 html 文件中。它总是有帮助的。
【解决方案2】:

您可以在一个 div 中加载您想要的所有内容,您必须使用 ng-template 和 ng-content。

首先你必须创建一个指令:

import {Directive, ViewContainerRef} from '@angular/core';

@Directive({
  selector: '[dynamic]',
  exportAs: 'dynamicdirective'
})
export class DynamicDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

你必须把它放在一些 ng-template 中,比如:

<p>
  page works!
</p>


<ng-template #sider=dynamicdirective dynamic></ng-template>

并像使用它一样

import {Component, ComponentFactoryResolver, OnInit, ViewChild} from '@angular/core';


@Component({
  selector: 'app-page',
  templateUrl: './page.component.html',
  styleUrls: ['./page.component.css']
})
export class PageComponent implements OnInit {

  @ViewChild('sider')
  sider;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
    
      const componentFactory = this.componentFactoryResolver.resolveComponentFactory(SomeComponent);
 this.sider.viewContainerRef.createComponent(componentFactory);
    });
   
  }

}

通常会看到你的组件加载在你的 ng-template 的位置(如果你想重置你的视图,你可以打电话给https://angular.io/api/core/ViewContainerRef#clear

我已经玩过了,你可以在这里找到一些代码https://github.com/nicearma/dynamic

【讨论】:

  • 感谢您的回答,viewchild 本身就是动态的。整个视图是在运行时动态创建的。所以,我使用 ng-template 指令解决了它。我今天会发布答案。
  • @Just code:你是如何将动态html加载到组件的div中的?
  • @user2439903 通过解析工厂实例?
【解决方案3】:

我想把这里留给以后遇到同样问题的人。

如果您不想像其他答案所建议的那样使用ComponentFactory 手动实例化组件,您还可以使用我为将组件加载到动态内容中的明确目的而编写的库:ngx-dynamic-hooks

您可以给它任何包含所需组件选择器的字符串,它将自动加载到它的位置。您甚至可以通过其他文本模式加载组件,而不仅仅是它们的选择器!亲身体验in this Stackblitz

如果您需要,还有更多花里胡哨的功能。在上面的链接中,您会找到一个相当详细的文档,应该可以轻松设置。

【讨论】:

    猜你喜欢
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2017-10-12
    • 1970-01-01
    • 2020-11-06
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多