Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load dynamic HTML into DIV with component? Angular5

I have been trying to find the solution of this problem from two days. Unfortunately, I can not get what I want. I am using Angular5.

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

This is what my function looks like:

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

Everything works fine, unless The html which I am returning contains one package named Select2 This is what I use to add the html into this div it works very fine. Until I wanted to add the dynamic package.

What I mean is return html contains the package component like this:

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

This just returns the plain text to the browser and doesn't work as expected.

What I want is the string to be turned into component or any other way which works and generates the select2 dropdown.

I have been trying to search so many things.But it doesn't works This is good but I can not understand this And dynamiccomponentloading is deprecated.

Can anyone please give me an idea How can I resolve this problem? Any example would be a great.

like image 224
Just code Avatar asked Jan 08 '18 16:01

Just code


People also ask

Which of the following directives is used to add a component at runtime in angular5?

The anchor directivelink AdDirective injects ViewContainerRef to gain access to the view container of the element that will host the dynamically added component. In the @Directive decorator, notice the selector name, adHost ; that's what you use to apply the directive to the element.

How do I render a string with HTML tag in angular 8?

To render a html string in angular, we can use the innerHTML property by binding a string to it. The innerHTML property sanitizes the html, so that your app is safe from the cross-site scripting attacks(XSS).


2 Answers

As commented by @Devcon

Angular will sanitize pretty much everything so that is why you are getting plain text. What you want to look into is ReflectiveInjector and mainly ComponentFactoryResolver. The main idea is that components need some other info(services, other components, etc) to be rendered, so you use the Injector to get Dependency Injection refs then the Component factory builds your component. You then insert this to a ViewChild reference. There is a more complicated way of dynamically making components that uses the compiler and requires a ModuleWithComponentFactories, this is what angular actually uses.

And searching on the angular, I accept that angular should not be done this way.

As I have to create the fully dynamic page which must be rendered in html. I changed my json little bit and using the ng-container and ng-template and using ngswitch I made recursive call in the template it self and found its working very fine.

I get many advantages using this: The HTML (I render dynamically) itself is in HTML, Code is clean and readable, easily maitainable.

The example given here is pretty much the same I have done. https://stackoverflow.com/a/40530244/2630817

A small example is here:

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

like image 106
Just code Avatar answered Oct 06 '22 01:10

Just code


You can load every you want in one div, you have to play with ng-template and ng-content.

First you have to create one directive:

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

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

  constructor(public viewContainerRef: ViewContainerRef) { }

}

After you have to put it in some ng-template like:

<p>
  page works!
</p>


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

and use it like

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);
    });
   
  }

}

and normally will see you component loaded at the place of you ng-template (you can call https://angular.io/api/core/ViewContainerRef#clear if you want to reset your view)

I already play with this, you can find some code here https://github.com/nicearma/dynamic

like image 24
nicearma Avatar answered Oct 06 '22 01:10

nicearma