离子6-动态组件加载器中的ViewChild Null
我正在开发一个离子应用程序,该应用程序将具有由JSON数据创建的控件的形式。
load-child.directive.ts:
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamicChild]'
})
export class DynamicChildLoaderDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
app.module.ts:
...
@NgModule({
declarations: [AppComponent, DynamicChildLoaderDirective],
...
home.page.html
...
<ion-content [fullscreen]="true" class="ion-padding">
<form [formGroup]="testForm">
<ion-card *ngFor="let objGrupo of grupos">
<ion-card-header>
<ion-card-title>{{objGrupo.label}}</ion-card-title>
</ion-card-header>
<ion-card-content *ngFor="let objControl of objGrupo.controls">
<app-dynamic-form [control]="objControl" [form]="testForm"></app-dynamic-form>
</ion-card-content>
</ion-card>
</form>
</ion-content>
...
home.page.ts:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DynamicFormGroup } from '../models/dynamic_form_group';
import { Ticket } from '../models/ticket';
import { TicketService } from '../services/ticket.service';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
grupos: DynamicFormGroup[] = [];
testControl: any = {};
testForm: FormGroup;
validation_messages: any;
constructor(public formBuilder: FormBuilder,private ticketService: TicketService) {
this.ticketService.obtenerFormularioTicket()
.subscribe(obtainedInfo => {
var ticket: Ticket = obtainedInfo;
this.grupos = ticket.getFormList();
this.testControl = this.grupos[0].controls;
});
}
}
dynamic-form.component.ponent.html:
<ion-label>{{ control.Name }}</ion-label>
<ng-template dynamicChild></ng-template>
dynamic-form.component.ts.ts:
import { Component, Input, OnInit, Type, ViewChild } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { DynamicChildLoaderDirective } from 'src/app/directives/load-child.directive';
import { DnElement } from '../dn-element/dn-element.component';
import { DnInputTextComponent } from '../dn-input-text/dn-input-text.component';
import { DnLabelComponent } from '../dn-label/dn-label.component';
@Component({
selector: 'app-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.scss'],
})
export class DynamicFormComponent implements OnInit {
@ViewChild(DynamicChildLoaderDirective, { static: true }) dynamicChild!: DynamicChildLoaderDirective;
@Input() control: any;
@Input() form: FormGroup;
componente: Type<any>;
ngOnInit(): void {
this.loadDynamicComponent();
}
private loadDynamicComponent() {
if(!this.control.Editable){
this.componente = DnLabelComponent;
}else{
this.componente = DnInputTextComponent;
}
const componentRef = this.dynamicChild.viewContainerRef.createComponent<DnElement>(this.componente);
componentRef.instance.objControl = this.control;
componentRef.instance.form = this.form;
}
}
问题是在运行应用程序时,问题是线路
const componentRef = this.dynamicChild.viewContainerRef.createComponent<DnElement>(this.componente);
返回以下错误:
ERROR Error: Uncaught (in promise): TypeError: this.dynamicChild is undefined
我使用以下版本:
离子版本:6.1.5
角版本:13.3.5
i我使用官方角文档作为指南:
https://angular.io/guide/dynamic-component-loader-loader
我试图将视图奇迹的静态属性更改为false并移动ngoninit到ngafterviewinit的结果相同。
这里有什么缺少的吗?
提前致谢。
编辑:
我也尝试使用ViewChildren:
export class DynamicFormComponent implements OnInit {
@ViewChild(DynamicChildLoaderDirective, { static: true }) dynamicChild!: DynamicChildLoaderDirective;
@ViewChildren(DynamicChildLoaderDirective) viewChildren!: QueryList<DynamicChildLoaderDirective>;
@Input() control: any;
@Input() form: FormGroup;
componente: Type<any>;
ngOnInit(): void {
//this.loadDynamicComponent();
}
ngAfterViewInit() {
// viewChildren is set
this.viewChildren.changes.subscribe((r) => {
console.log(this.viewChildren);
});
}
没有错误的出现,但它永远不会进入订阅的Console.Log部分。
I´m developing an Ionic application that will have a form with controls created dinamically from JSON data.
load-child.directive.ts:
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamicChild]'
})
export class DynamicChildLoaderDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
app.module.ts:
...
@NgModule({
declarations: [AppComponent, DynamicChildLoaderDirective],
...
home.page.html
...
<ion-content [fullscreen]="true" class="ion-padding">
<form [formGroup]="testForm">
<ion-card *ngFor="let objGrupo of grupos">
<ion-card-header>
<ion-card-title>{{objGrupo.label}}</ion-card-title>
</ion-card-header>
<ion-card-content *ngFor="let objControl of objGrupo.controls">
<app-dynamic-form [control]="objControl" [form]="testForm"></app-dynamic-form>
</ion-card-content>
</ion-card>
</form>
</ion-content>
...
home.page.ts:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DynamicFormGroup } from '../models/dynamic_form_group';
import { Ticket } from '../models/ticket';
import { TicketService } from '../services/ticket.service';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
grupos: DynamicFormGroup[] = [];
testControl: any = {};
testForm: FormGroup;
validation_messages: any;
constructor(public formBuilder: FormBuilder,private ticketService: TicketService) {
this.ticketService.obtenerFormularioTicket()
.subscribe(obtainedInfo => {
var ticket: Ticket = obtainedInfo;
this.grupos = ticket.getFormList();
this.testControl = this.grupos[0].controls;
});
}
}
dynamic-form.component.html:
<ion-label>{{ control.Name }}</ion-label>
<ng-template dynamicChild></ng-template>
dynamic-form.component.ts:
import { Component, Input, OnInit, Type, ViewChild } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { DynamicChildLoaderDirective } from 'src/app/directives/load-child.directive';
import { DnElement } from '../dn-element/dn-element.component';
import { DnInputTextComponent } from '../dn-input-text/dn-input-text.component';
import { DnLabelComponent } from '../dn-label/dn-label.component';
@Component({
selector: 'app-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.scss'],
})
export class DynamicFormComponent implements OnInit {
@ViewChild(DynamicChildLoaderDirective, { static: true }) dynamicChild!: DynamicChildLoaderDirective;
@Input() control: any;
@Input() form: FormGroup;
componente: Type<any>;
ngOnInit(): void {
this.loadDynamicComponent();
}
private loadDynamicComponent() {
if(!this.control.Editable){
this.componente = DnLabelComponent;
}else{
this.componente = DnInputTextComponent;
}
const componentRef = this.dynamicChild.viewContainerRef.createComponent<DnElement>(this.componente);
componentRef.instance.objControl = this.control;
componentRef.instance.form = this.form;
}
}
The problem is when running the application, the line
const componentRef = this.dynamicChild.viewContainerRef.createComponent<DnElement>(this.componente);
returns the following error:
ERROR Error: Uncaught (in promise): TypeError: this.dynamicChild is undefined
I´m using the following versions:
Ionic Version: 6.1.5
Angular Version: 13.3.5
I´m Using the offical angular docs as guide:
https://angular.io/guide/dynamic-component-loader
I´ve tried to change the static property of the ViewChild to false and move the ngOnInit to the ngAfterViewInit with the same result.
Is there anything missing here?
Thanks in advance.
Edit:
I´ve also tried with viewChildren:
export class DynamicFormComponent implements OnInit {
@ViewChild(DynamicChildLoaderDirective, { static: true }) dynamicChild!: DynamicChildLoaderDirective;
@ViewChildren(DynamicChildLoaderDirective) viewChildren!: QueryList<DynamicChildLoaderDirective>;
@Input() control: any;
@Input() form: FormGroup;
componente: Type<any>;
ngOnInit(): void {
//this.loadDynamicComponent();
}
ngAfterViewInit() {
// viewChildren is set
this.viewChildren.changes.subscribe((r) => {
console.log(this.viewChildren);
});
}
No error presents but it never enters the console.log part of the subscribe.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
最后,我设法使它起作用。代码是可以的,不同的是,必须在我使用的页面中执行该指令的声明。在这种情况下
Finally I managed to get it work. The code is ok as is, with the difference that the declaration of the directive has to be done in the page in which I´m using it. In this case in home.module.ts instead of app.module.ts:
当您的页面满载时,您应该调用模板引用,为此,当您的页面满载时,我们会触发生命周期挂钩:
You should call template references when your page fully loaded and for that We have a lifecycle hooks triggered when your page fully loaded:
尝试一下
try this