Angular 将数据从服务传递到组件-->;子组件

Angular 将数据从服务传递到组件-->;子组件,angular,firebase,rxjs,angular-services,angular4-forms,Angular,Firebase,Rxjs,Angular Services,Angular4 Forms,简而言之,我用的是这个 我有一个场景,我必须通过从服务读取元素数据来动态创建控件。因此,当我从服务读取数据时,它是异步的,但我必须根据从服务接收到的数据创建一些具体的对象,并将其传递给子组件。这就是我的逻辑 主要组件的Html如下所示 <ion-content padding class="container" *ngIf="questions"> <app-dynamic-form [questions]="questions"></app-dyn

简而言之,我用的是这个 我有一个场景,我必须通过从服务读取元素数据来动态创建控件。因此,当我从服务读取数据时,它是异步的,但我必须根据从服务接收到的数据创建一些具体的对象,并将其传递给子组件。这就是我的逻辑

主要组件的Html如下所示

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

}
Class ComponentMain{
@输入()问题:问题库[]=[];
构造函数(公共navCtrl:NavController、公共navParams:navParams、私有qcs:Service)
{
qcs.getQuestions(this.parameter1.$key).subscribe(result=>this.questions=result);
}
}
子组件Html如下所示

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

 }

}
Class ChildComponent实现AfterViewInit{
@输入()问题:问题库[]=[];
构造函数(){
}
ngAfterViewInit(){
this.form=this.qcs.toFormGroup(this.questions);
}
}
第二个子组件依赖于childComponent来创建控件。因此,控件仅在第二个子组件的ngOnit中填充,因此不会创建控件。我试着使用很多生命周期挂钩,比如OnInit、OnChanges等,但没有一个真正给了我结果。我确信我错过了一些我无法理解的东西

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
      }))
  }
 }
}
Class服务(){
问题:问题数据[]=[];
getQuestions(FormKey:string){
var dbQuestions=this.af.list(“/elements”{
查询:{
限时:200,
orderByChild:“formid”,
等号:FormKey
}
})
dbQuestions.subscribe(快照=>{
snapshots.forEach(elementData=>{
this.questions.push(新文本框问题({
键:elementData.elementname,
标签:elementData.displaytext,
值:elementData.elementvalue,
必填项:false,
订单:elementData.sortorder
}))
}
}
}

我不确定是否理解您的问题,但当我需要将数据从服务传递到组件时,我会以这种方式使用subscription

两个组件(父组件及其子组件或其他不同组件)可以共享其接口支持双向通信的服务

与观察者模式类似,在本例中,服务实例的范围是来自组件(发布者)和其他组件(订阅者)的通知

mycomponent.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class MyComponentService{
    // Observable 
    private sampleObservable = new Subject<boolean>();
    // Observable boolean streams
    sampleSubscriber = this.sampleObservable.asObservable();
    // Event for notification from publisher to subscriber
    sampleEventChanged(value:boolean)
    {
        this.sampleObservable.next();
    }
}
import { Component } from '@angular/core';
import { MyService } from './mycomponent.service';

@Component({
  selector: 'app-my-control-publisher',
  template: `
  <h2>This is the publisher control</h2>
  <button (click)="announce()">Announce to subscriber</button>
  `,
  providers: [MyService]
})

export class MyControlPublisherComponent 
{
  constructor(private myService: MyService) { }

  announce() 
  {
    this.myService.sampleEventChanged(true);
  }
}
import { Component, OnDestroy } from '@angular/core';
import { MyService } from './mycomponent.service';
import { Subscription } from 'rxjs/Subscription';

@Component({
 selector: 'app-my-control-subscriber',
 template: `
 <h2>This is the subscriber control</h2>
 `,
})

export class MyControlSubscriberComponent 
{
  // Subscriptions
  private componentSubscription: Subscription;

  constructor(private myService: MyService) 
  {
    // Subscription of the notifications
    this.componentSubscription= this.myService.sampleSubscriber.subscribe(value =>
    {
      // Put the code for manage the notification here
    }
  }

  ngOnDestroy()
  {
    // Release subscription to avoid memory leaks when the component is destroyed
    this.componentSubscription.unsubscribe();
  }
}
从'@angular/core'导入{Injectable};
从'rxjs/Subject'导入{Subject};
@可注射()
导出类MyComponentService{
//可见
private sampleObservable=新主题();
//可观察的布尔流
sampleSubscriber=this.sampleObservable.asObservable();
//从发布服务器通知订阅服务器的事件
sampleEventChanged(值:布尔值)
    {
this.sampleObservable.next();
    }
}
在要通知所有订阅者其状态更改的组件中:

mycomponent publisher.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class MyComponentService{
    // Observable 
    private sampleObservable = new Subject<boolean>();
    // Observable boolean streams
    sampleSubscriber = this.sampleObservable.asObservable();
    // Event for notification from publisher to subscriber
    sampleEventChanged(value:boolean)
    {
        this.sampleObservable.next();
    }
}
import { Component } from '@angular/core';
import { MyService } from './mycomponent.service';

@Component({
  selector: 'app-my-control-publisher',
  template: `
  <h2>This is the publisher control</h2>
  <button (click)="announce()">Announce to subscriber</button>
  `,
  providers: [MyService]
})

export class MyControlPublisherComponent 
{
  constructor(private myService: MyService) { }

  announce() 
  {
    this.myService.sampleEventChanged(true);
  }
}
import { Component, OnDestroy } from '@angular/core';
import { MyService } from './mycomponent.service';
import { Subscription } from 'rxjs/Subscription';

@Component({
 selector: 'app-my-control-subscriber',
 template: `
 <h2>This is the subscriber control</h2>
 `,
})

export class MyControlSubscriberComponent 
{
  // Subscriptions
  private componentSubscription: Subscription;

  constructor(private myService: MyService) 
  {
    // Subscription of the notifications
    this.componentSubscription= this.myService.sampleSubscriber.subscribe(value =>
    {
      // Put the code for manage the notification here
    }
  }

  ngOnDestroy()
  {
    // Release subscription to avoid memory leaks when the component is destroyed
    this.componentSubscription.unsubscribe();
  }
}
从'@angular/core'导入{Component};
从“/mycomponent.service”导入{MyService};
@组成部分({
选择器:“应用程序我的控件发布者”,
模板:`
这是发布者控件
向订户宣布
`,
提供者:[MyService]
})
导出类MyControlPublisherComponent
{
构造函数(私有myService:myService){}
宣布
{
this.myService.sampleEventChanged(true);
}
}
在订阅服务器组件中,要获取通知的用户

mycomponent订户.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class MyComponentService{
    // Observable 
    private sampleObservable = new Subject<boolean>();
    // Observable boolean streams
    sampleSubscriber = this.sampleObservable.asObservable();
    // Event for notification from publisher to subscriber
    sampleEventChanged(value:boolean)
    {
        this.sampleObservable.next();
    }
}
import { Component } from '@angular/core';
import { MyService } from './mycomponent.service';

@Component({
  selector: 'app-my-control-publisher',
  template: `
  <h2>This is the publisher control</h2>
  <button (click)="announce()">Announce to subscriber</button>
  `,
  providers: [MyService]
})

export class MyControlPublisherComponent 
{
  constructor(private myService: MyService) { }

  announce() 
  {
    this.myService.sampleEventChanged(true);
  }
}
import { Component, OnDestroy } from '@angular/core';
import { MyService } from './mycomponent.service';
import { Subscription } from 'rxjs/Subscription';

@Component({
 selector: 'app-my-control-subscriber',
 template: `
 <h2>This is the subscriber control</h2>
 `,
})

export class MyControlSubscriberComponent 
{
  // Subscriptions
  private componentSubscription: Subscription;

  constructor(private myService: MyService) 
  {
    // Subscription of the notifications
    this.componentSubscription= this.myService.sampleSubscriber.subscribe(value =>
    {
      // Put the code for manage the notification here
    }
  }

  ngOnDestroy()
  {
    // Release subscription to avoid memory leaks when the component is destroyed
    this.componentSubscription.unsubscribe();
  }
}
从'@angular/core'导入{Component,OnDestroy};
从“/mycomponent.service”导入{MyService};
从'rxjs/Subscription'导入{Subscription};
@组成部分({
选择器:“应用程序我的控制订阅服务器”,
模板:`
这是订户控件
`,
})
导出类MyControlSubscriberComponent
{
//订阅
私有组件订阅:订阅;
构造函数(私有myService:myService)
{
//订阅通知
this.componentSubscription=this.myService.sampleSubscriber.subscripte(值=>
{
//将用于管理通知的代码放在此处
}
}
恩贡德斯特罗()
{
//释放订阅以避免组件销毁时内存泄漏
this.componentSubscription.unsubscribe();
}
}
我希望这能对您有所帮助。

看看这个示例,它本质上是在运行时从元数据构建表单

有几条评论指出示例还没有完成

@Injectable()
导出类查询服务{
//Todo:从问题元数据的远程源获取
//Todo:使异步
getQuestions(){
...
以下是我完成并清除错误消息所采取的步骤


问题.service.ts 将
getQuestions
更改为异步返回问题

Injectable()
导出类查询服务{
建造师(
专用http:http
) {}
getQuestions$(){
常量url=https://api.myjson.com/bins/d0srd';
返回此.http.get(url)
.map(response=>response.json())
.map(questionMetadata=>this.metadataToQuestions(questionMetadata))
.map(questions=>questions.sort((a,b)=>a.order-b.order))
}
私有元数据问题(问题元数据){
返回questionMetadata.questions.map(this.toQuestion)
}
私人问题(elementData){
//展开以获取其他控件类型
返回新的TextboxQuestion({
键:elementData.elementname,
标签:elementData.displaytext,
值:elementData.elementvalue,
必填项:false,
订单:elementData.sortorder
})
}
}

app.component.ts 已更改变量<代码>问题