简体   繁体   中英

Angular 7 dynamically load @Component

I'm trying to dynamically add components to my @Component template the components are populating but the tool bar does not change when I change the "buttonstring" variable.

I have a component..

@Component({
selector: 'map-toolbar-action',
template:'<p style="position: absolute;z- 
index:5000">' + mapValues.buttonString + 
'</p>',
styleUrls: ['./map-toolbar- 
action.component.scss']
})
export class MapToolbarActionComponent 
implements OnInit {

constructor() {
mapValues.buttonString = 
mapValues.arrayToString(mapValues.buttons);
}

ngOnInit() {
}

}

I have a singleton with these elements...

public static buttonString = "<component1></component1><component2></component2><component3></component3>";

I was hoping that I could then change buttonString to add, subtract or completely replace the list of components and the toolbar would update.

buttonString = "<component2></component2><component3></component3>";
buttonString = "<component1></component1><component2></component2><component3></component3><component4></component4>";
buttonString = "<componentA></componentA><componentB></componentB><componentC></componentC>;

and that would in-turn update the components to the template but it's not working like that...how can I accomplish this?

Any help is greatly appreciated!!

You can not change the template using the way you're trying. the template it's read only one time at the very initial stage of the application. I suppose you can achieve it using *ngIf or "adding dynamically components" using ComponentFactoryResolver . To add dynamically a component, first, you need to declare in "entryComponents" of your module

  entryComponents:[HelloComponent]

Then, create a .html like

<ng-template #container>
</ng-template>

Your main.component.ts

  @ViewChild('container', { static: true, read: ViewContainerRef }) entry: ViewContainerRef;

  constructor(private resolver: ComponentFactoryResolver) { }

  ngOnInit()
  {
    this.entry.clear();
    const factory = this.resolver.resolveComponentFactory(HelloComponent);
    const componentRef = this.entry.createComponent(factory);
    componentRef.instance.name = this.name;
  }

See a simple example in stackblitz

It appears that you can load components initially using "template"

template:'<p style="position: absolute;z-index:5000">' + components + '</p>'
**Global variable somewhere
public static components = "<component1></component1><component2></component2> 
<component3></component3>"

You cannot use 2 way binding to change this string and dynamically populate components. I couldn't figure out how to get ComponentFactoryResolver to meet my needs so... What I've done is handle this with a global state variable and *ngIf in the parent component toolbar html that contains my tool components

<p *ngIf="myAppStateValue ==='foo'">
<component-one></component-one>
<component-two></component-two>
<component-three></component-three>
</p>
<p *ngIf="myAppStateValue ==='bar'">
<component-three></component-three>
<component-four></component-four>
<component-five></component-five>
</p>

Then I also added an *ngIf to the Parent application html that loads the tool bars

 <div *ngIf="formValues.mapState !='custom'"><toolbar-1></toolbar-1> 
 </div>
 <div *ngIf="formValues.mapState =='custom'"><custom-toolbar></custom-toolbar></div>

When the app loads it loads the global "components" variable with whatever the user has determined they want their "custom" tools to be.

public static components = "<component1></component1><component2></component2> 
<component3></component3>"

and then in the custom toolbar i use the "template" parameter to load the components

template:'<p style="position: absolute;z-index:5000">' + components + '</p>'

If you want to dynamically add components yet unknown to you, and do so in declarative fashion, you need to use ngComponentOutlet :

https://angular.io/api/common/NgComponentOutlet

You would need to add your component to entryComponents of some module and then pass it to ngComponentOutlet . If you are using lazy modules — make sure you pass Injector that's aware of that entryComponents , see:

https://angular.io/api/common/NgComponentOutlet

Funn_Bobby seems to have long solved this by now via *ngIf in templates. For all who are in a similar scenario though or need an even more flexible solution, I've written a library for the explicit purpose of easily loading components from strings: ngx-dynamic-hooks . Have at look at it live here . Just wanted to leave it here in case it helps someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM