首页 文章

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

提问于
浏览
1

非常简短我正在使用Plunker我有一个场景,我必须通过从服务中读取元素数据来动态创建控件 . 因此,当我从服务中读取数据时,它是异步的 . 但是我必须根据从服务接收的数据创建一些具体对象,并将其传递给子组件 . 所以这是我的逻辑

主要组件的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);
    }

}

子组件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);

 }

}

有一个第二个子组件依赖于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
      }))
  }
 }
}

2 回答

  • 2

    查看此示例Angular.io - Dynamic Forms,它实质上是在运行时从元数据构建表单 .

    有几条评论表明这个例子还没有完成 .

    @Injectable()
    export class QuestionService {
    
      // Todo: get from a remote source of question metadata
      // Todo: make asynchronous
      getQuestions() {
      ...
    

    这些是我完成它并清除错误消息所采取的步骤 .

    question.service.ts

    更改 getQuestions 以异步方式返回问题 .

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

    app.component.ts

    将变量 questions 类型更改为observable,将异步管道添加到模板 .

    @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$();
      }
    }
    

    dynamic-form.component.ts

    将@Input变量 questions 更改为set / get style,以处理初始null值 .
    更改了从 ngOnInitngOnChanges 创建表单的挂钩,以处理问题的异步到达 .

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

    dynamic-form-question.component.ts

    添加额外的检查到 isValid getter以确保存在验证的控件 .

    export class DynamicFormQuestionComponent {
      ...
      get isValid() { return this.form.controls[this.question.key] 
        ? this.form.controls[this.question.key].valid : true; }
    }
    
  • 0

    我不确定我是否理解你的问题,但是当我需要将数据从服务传递到组件时,我就这样使用订阅 .

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

    与Observer模式类似,在这种情况下,服务实例的范围是来自组件(Publisher)和其他组件(订阅者)的通知 .

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

    在想要通知所有订户状态更改的组件中:

    mycomponent-publisher.ts

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

    在想要获取通知的订户组件中 .

    mycomponent-subscriber.ts

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

    我希望这可以帮到你 .

相关问题