【问题标题】:Display <my-component> by [innerHTML]通过 [innerHTML] 显示 <my-component>
【发布时间】:2018-12-21 01:49:14
【问题描述】:

我试图将我的自定义组件标签放在一个字符串数组中,并在通过调用 bypassSecurityTrustHtml 对它们进行清理后通过 ngfor 将它们绑定到 innerhtml 属性......不幸的是,输出始终为空,但也没有清理错误。 ..

我做错了什么?

// adminpanel.component.ts
@Component({
    selector: 'admin-panel',
    templateUrl: './adminpanel.component.html'
})
export class AdminPanelComponent {

    static GetRoutes(): Route[] {
        return [
            { path: '', redirectTo: 'news', pathMatch: 'full' },

        // 0
            { path: 'news', component: AdminNewsViewComponent },
        // 1
            { path: 'users', component: AdminUsersViewComponent },
        // 2
            { path: 'roles', component: AdminRolesViewComponent },
        // 3
            {
                path: 'culturesettings',
                redirectTo: 'culturesettings/wordvariables'
            },
            {
                path: 'culturesettings', 
                component: AdminCultureSettingsViewComponent,
                pathMatch: 'prefix',
                children: AdminCultureSettingsViewComponent.GetRoutes()
            },
        // 4
            {
                path: 'account',
                component: AdminAccountViewComponent
            }
        ]
    }

    panels: AdminPanel[] = [];

    routedTabs: RoutedTabs

    constructor(private authService: AuthService, private routerService: RouterService, private sanitizer: DomSanitizer) {
        this.routedTabs = new RoutedTabs("admin/panel", 2, authService, routerService);

        var routes = AdminPanelComponent.GetRoutes().filter(x => x.component != undefined);
        var comps = [
            '<admin-news-view></admin-news-view>',
            '<admin-users-view></admin-users-view>',
            '<admin-roles-view></admin-roles-view>',
            '<admin-culture-settings-view></admin-culture-settings-view>',
            '<admin-account-view></admin-account-view>'
        ];
        for (var i = 0; i < comps.length; i++) this.panels.push(new AdminPanel(i, routes[i], this.sanitizer.bypassSecurityTrustHtml(comps[i])  , this.sanitizer));

    }

    ngOnInit() {

        this.routedTabs.MakeTabs(AdminPanelComponent.GetRoutes());
        this.routedTabs.Subscribe();
        this.routedTabs.Emit();
    }
    ngOnDestroy() {
        this.routedTabs.Unsubscribe()
    }
}
class AdminPanel {
    index: number;
    route: Route;
    innerHtml: any = '';
    constructor(index: number, route: Route, innerHtml: any, private sanitizer: DomSanitizer) {
        this.index = index;
        this.route = route;
        this.innerHtml = innerHtml;

    }
}

在我的 adminpanel.component.html 中:

<mat-tab-group (selectedTabChange)="routedTabs.onTabChange($event)" [(selectedIndex)]="routedTabs.selectedTab">
    <mat-tab *ngFor="let panel of panels" label="{{ routedTabs.tabs[panel.index].label }}">
        <div [innerHTML]="panel.innerHtml">

        </div>
    </mat-tab>
</mat-tab-group>

【问题讨论】:

  • Angular 默认清理所有内容 - angular.io/guide/… - 你为什么要自己做?
  • @WandMaker 因为如果我尝试直接输出字符串,那么控制台会警告我某些内容已被清理并且“”例如将被视为威胁,即使它是我自己的组件,我想将其显示为可以在 ngfor 循环中使用的变量
  • 我不确定我是否正确理解了您的问题?你想通过将组件标签作为字符串放入 innerhtml 属性来呈现自己的组件吗?
  • @SirDieter 是的,这正是我想要的,我该如何实现?
  • 仅仅使用标签作为字符串是行不通的,因为如果在 dom 中弹出一个匹配选择器的元素,Angular 不会创建组件实例。

标签: javascript angular components ngfor angular-dom-sanitizer


【解决方案1】:

据我所知,这并没有真正以令人满意或干净的方式解决。我一直在同一条船上,也没有找到在动态字符串中加载组件的好解决方案 - 所以我用ngx-dynamic-hooks编写了我自己的!

您可能感兴趣的一些关键点:

  • 查找字符串中的所有组件选择器并自动加载相应的组件
  • 如果你需要的话,甚至可以通过其他文本模式而不是选择器来加载组件
  • 输入和输出可以像在普通模板中一样设置,并自动为您从字符串解析为实际变量
  • 组件可以不受限制地嵌套,并且会按预期出现在彼此的“ng-content”槽中
  • 您可以将来自父组件的实时数据传递到动态加载的组件中(甚至可以使用它来绑定内容字符串中的输入/输出)
  • 您可以精确控制允许在出口到出口的基础上加载哪些组件,甚至可以为它们提供哪些输入/输出
  • 您可以选择将组件配置为仅在需要时才延迟加载
  • 该库使用 Angular 的内置 DOMSanitizer,即使输入可能不安全也可以安全使用

组件是使用原生 Angular 方法创建的,其行为与您应用中的任何其他组件一样。我希望这对所有遇到同样问题的人有所帮助。

看到它在行动in this Stackblitz

【讨论】:

  • 赞成一件令人满意的事情,这在 2 年前对我很有帮助。不幸的是,这个问题已经使用上一个答案中的 Component Factory Resolver 解决了......但你是对的答案以令人满意且干净的方式编写!希望它为将来寻找与我相同答案的人们提供服务。
  • 谢谢!是的,我认为这个问题可能早就解决了,但希望它可以让其他人付出一些努力。
【解决方案2】:

仅将标签用作字符串是行不通的,因为如果在 dom 中弹出具有匹配选择器的元素,则 Angular 不会创建组件实例。

你也可以

  1. 使用ComponentFactoryResolver
  2. 只需在面板上有一个类型属性,因此您可以根据类型使用ngSwitch,并在ngSwitchCase 中呈现相应的属性。在这种情况下,您的模板中会包含标签

【讨论】:

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