javascript - Hvordan laste dynamisk HTML inn i DIV med komponent? Angular5
Jeg har prøvd å finne løsningen på dette problemet i to dager. Dessverre kan jeg ikke få det jeg ønsker. Jeg bruker Angular5.
<div class="form-group col-md-12" [innerHTML]="GetItemsOfHolder(item.children[1],1,
'UserConfigGroupsLabelHolder') | keepHtml"></div>
Slik ser funksjonen min ut:
GetItemsOfHolder(item: any,divName:string, recursive: boolean = false,typeName:string="")
{
return html;
}
Alt fungerer fint, med mindre HTML-en jeg returnerer inneholder en pakke som heter Select2. Dette er det jeg bruker for å legge HTML-en inn i denne div-en, det fungerer veldig bra. Inntil jeg ønsket å legge til den dynamiske pakken.
Det jeg mener er at returnert HTML inneholder pakkekomponenten slik:
itemhtml +="<select2 data-type='"+holderItem.itemType+"'
[data]='this.dropdownData."+holderItem.name+"'></select2>"
Dette returnerer bare ren tekst til nettleseren og fungerer ikke som forventet.
Det jeg ønsker er at strengen blir gjort om til en komponent eller på en annen måte som fungerer og genererer select2-nedtrekksmenyen.
Jeg har prøvd å søke etter så mange ting. Men det fungerer ikke. Dette er bra, men jeg kan ikke forstå dette. Og dynamiccomponentloading er foreldet.
Kan noen være så snill å gi meg en idé om hvordan jeg kan løse dette problemet? Et eksempel ville vært flott.
Svar #1
Som kommentert av @Devcon
Angular vil rense nesten alt, så det er derfor du får vanlig tekst. Det du bør se nærmere på er ReflectiveInjector og hovedsakelig ComponentFactoryResolver. Hovedideen er at komponenter trenger litt annen informasjon (tjenester, andre komponenter osv.) for å bli gjengitt, så du bruker Injector for å få Dependency Injection-referanser, og deretter bygger komponentfabrikken komponenten din. Du setter så dette inn i en ViewChild-referanse. Det finnes en mer komplisert måte å lage komponenter dynamisk på som bruker kompilatoren og krever et ModuleWithComponentFactories; dette er det Angular faktisk bruker.
Og ved å søke på Angular, aksepterer jeg at Angular ikke bør gjøres på denne måten.
Siden jeg må lage en fullstendig dynamisk side som må rendres i HTML, endret jeg JSON-en min litt og bruker ng-container og ng-template, og ved å bruke ngswitch laget jeg et rekursivt kall i selve malen og fant ut at det fungerer veldig bra.
Jeg får mange fordeler ved å bruke dette: HTML-en (som jeg gjengir dynamisk) er i HTML, koden er ren og lesbar, lett å vedlikeholde.
Eksemplet som gis her er stort sett det samme som jeg har gjort. https://stackoverflow.com/a/40530244/2630817
Et lite eksempel er her:
<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>
Svar #2
Du kan laste inn alt du vil i en div, du må leke med ng-template og ng-content.
Først må du lage en direktiv:
import {Directive, ViewContainerRef} from '@angular/core';
@Directive({
selector: '[dynamic]',
exportAs: 'dynamicdirective'
})
export class DynamicDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}Etterpå må du sette det i en eller annen ng-template som:
<p>
page works!
</p>
<ng-template #sider=dynamicdirective dynamic></ng-template>og bruk det som
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);
});
}
}og normalt vil du se komponenten din lastet på stedet til din ng-template (du kan kalle https://angular.io/api/core/ViewContainerRef#clear hvis du vil tilbakestille visningen din)
Jeg leker allerede med dette, du kan finne noe kode her https://github.com/nicearma/dynamic
