Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display <my-component> by [innerHTML]

I'm trying to have my custom component tags in a string array and bind them by ngfor to the innerhtml property after sanitizing them by calling bypassSecurityTrustHtml... unfortunately the output is always empty, but there is also no sanitize error...

What am i doing wrong?

// 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;

    }
}

And in my 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>
like image 611
Fy Z1K Avatar asked Aug 15 '26 20:08

Fy Z1K


1 Answers

From what I gather, this has not really been resolved in a satisfying or clean manner. I've been in the same boat and didn't find a good solution to loading components in dynamic strings either - so I've written my own with ngx-dynamic-hooks!

Some key points you might be interested in:

  • Finds all component selectors inside a string and autormatically loads the corresponding components in their place
  • Can even load components by other text pattern than their selectors, if that is what you need
  • Inputs and outputs can be set just like in a normal template and are automatically parsed from strings into actual variables for you
  • Components can be nested without restrictions and will appear in each others "ng-content"-slots as expected
  • You can pass live data from the parent component into the dynamically loaded components (and even use it to bind inputs/outputs in the content string)
  • You have meticulous control over which components are allowed to load on an outlet-to-outlet-basis and even which inputs/outputs you can give them
  • You can optionally configure components to lazy-load only when they are needed
  • The library uses Angular's built-in DOMSanitizer to be safe to use even with potentially unsafe input

The components are created with native Angular methods and behave just like any other component in your app. I hope this helps all who enounter the same problem.

See it in action in this Stackblitz.

like image 95
Mvin Avatar answered Aug 17 '26 09:08

Mvin