将数据从服务传递到组件->子组件 [英] Passing data from service to Component --> Child Components
问题描述
简而言之,我正在使用此柱塞 我有一种情况,我必须通过从服务读取元素数据来动态创建控件.因此,当我从服务中读取数据时,它是异步的.但是我必须基于从服务中接收到的数据创建一些具体对象,并将其传递给子组件.这就是我的逻辑
To be very short i am using this Plunker I have a scenario where i have to create controls dynamically by reading the elements data from a service. So when i read the data from the service its asynchronous.But i have to create some concrete objects based on the data i receive from the service and pass it to the child components. So here is my logic
主要成分的HTML如下.
Html for the Main Component is as below.
<ion-content padding class="container" *ngIf="questions">
<app-dynamic-form [questions]="questions"></app-dynamic-form>
</ion-content>
主要组件的类别如下
Class ComponentMain{
@Input() questions: QuestionBase<any>[]=[];
constructor(public navCtrl: NavController, public navParams: NavParams,private qcs: Service)
{
qcs.getQuestions(this.parameter1.$key).subscribe(result => this.questions = result);
}
}
Child Components Html如下.
Child Components Html is as follows.
<div *ngIf="form">
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let question of questions" class="form-row">
<div *ngIf="question">
<app-question [question]="question" [form]="form"></app-question>
</div>
</div>
</form>
</div>
子组件如下
Class ChildComponent implements AfterViewInit {
@Input() questions: QuestionBase<any>[] = [];
Constructor(){
}
ngAfterViewInit(){
this.form = this.qcs.toFormGroup(this.questions);
}
}
第二个子组件依赖于childComponent来创建控件.因此,仅在第二个子组件的ngOnit中填充了控件,因此未创建控件.我尝试使用许多生命周期挂钩,例如OnInit,OnChanges等.但是它们实际上都没有给我结果.我确定我缺少一些我无法弄清楚的东西.
There is a 2nd child component which depends on childComponent to create the controls. So the controls are getting populated only in ngOnit of the 2nd child Component and due to which the controls are not getting created. I tried to use many life cycle hooks such as OnInit,OnChanges etc. But none of them actually gave me the result. I am sure i am missing something that i am unable to figure it out.
Class Service(){
questions: QuestionsData<any>[]=[];
getQuestions(FormKey: string) {
var dbQuestions = this.af.list('/elements', {
query: {
limitToLast: 200,
orderByChild: 'formid',
equalTo: FormKey
}
})
dbQuestions.subscribe(snapshots=>{
snapshots.forEach(elementData => {
this.questions.push(new TextboxQuestion({
key: elementData.elementname,
label: elementData.displaytext,
value: elementData.elementvalue,
required: false,
order: elementData.sortorder
}))
}
}
}
推荐答案
看此示例 Angular.io-动态表单,它实际上是在运行时从元数据构建表单.
Looking at this example Angular.io - Dynamic Forms, it essentially builds a form from metadata at runtime.
有一些注释表明该示例尚未完成.
There's a couple of comments indicating that the example isn't quite finished.
@Injectable()
export class QuestionService {
// Todo: get from a remote source of question metadata
// Todo: make asynchronous
getQuestions() {
...
这些是我完成并清除错误消息的步骤.
These are the steps I took to finish it off and clean out the error messages.
已更改getQuestions
以异步返回问题.
Changed getQuestions
to asynchronously return questions.
Injectable()
export class QuestionService {
constructor(
private http: Http
) {}
getQuestions$() {
const url = 'https://api.myjson.com/bins/d0srd';
return this.http.get(url)
.map(response => response.json())
.map(questionMetadata => this.metadataToQuestions(questionMetadata))
.map(questions => questions.sort((a, b) => a.order - b.order))
}
private metadataToQuestions(questionMetadata) {
return questionMetadata.questions.map(this.toQuestion)
}
private toQuestion(elementData) {
// expand for additional control types
return new TextboxQuestion({
key: elementData.elementname,
label: elementData.displaytext,
value: elementData.elementvalue,
required: false,
order: elementData.sortorder
})
}
}
将变量questions
的类型更改为可观察,并向模板添加了异步管道.
Changed variable questions
type to observable, added async pipe to template.
@Component({
...
template: `
<div>
<h2>Job Application for Heroes</h2>
<app-dynamic-form [questions]="(questions$ | async)"></app-dynamic-form>
</div>
`,
...
})
export class AppComponent implements OnInit {
questions$: Observable<any>;
constructor(
private questionService: QuestionService
) {}
ngOnInit() {
this.questions$ = this.questionService.getQuestions$();
}
}
已将@Input变量questions
更改为设置/获取样式,以处理初始空值.
将创建表单的钩子从ngOnInit
更改为ngOnChanges
以处理问题的异步到达.
Changed @Input variable questions
to be set/get style, to handle initial null value.
Changed hook where form is created from ngOnInit
to ngOnChanges
to handle async arrival of questions.
export class DynamicFormComponent implements OnChanges {
private _questions = [];
@Input()
set questions(value: any[]) {
this._questions = value || [];
}
get questions(): any[] {
return this._questions;
}
...
ngOnChanges() {
this.form = this.qcs.toFormGroup(this.questions);
}
}
向isValid
获取器中添加其他检查,以确保要验证的控件存在.
Add additional check to isValid
getter to ensure the control being validated exists.
export class DynamicFormQuestionComponent {
...
get isValid() { return this.form.controls[this.question.key]
? this.form.controls[this.question.key].valid : true; }
}
这篇关于将数据从服务传递到组件->子组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!