Update several component properties with a single

2019-03-02 14:26发布

问题:

Previous post related : Angular2 : Reduce number of Http calls

The context is still the same : I'm trying to setup a "dico" component, that need an ID and a Language in input, and should give me some translated Text from my database.

dico.component.ts :

@Component({
    selector: 'dico',
    template: `{{text}}`  // => The text I'm trying to update
})

class Dico implements AfterViewInit {
    // Définition des paramètres et du texte en sortie
    @Input() private dicoID: string;
    @Input() private dicoLang: string;
    public text: string = null;

    constructor(private dicoService: DicoService) {
    }

    (...)
}

@Component({
    template: `<dico [dicoID] [dicoLang]></dico>`,
    directives: [Dico]
})

export class DicoComponent {

}  

usage in an HTML file :

<dico [dicoID]="dicoService.getDico('211800', 'en') | async"></dico>
<dico [dicoID]="dicoService.getDico('211801', 'en') | async"></dico>

with the following code in the .ts :

ngAfterViewInit() {
    this.dicoService.sendRequest();
}

I'm calling the "dicoService" to subscribe to these "dico"s and then send the resquest to my API that successfully gives me the results :

dico.service.ts :

@Injectable()
export class DicoService {
    private subjects = []
    private ids: string[] = [];

(...)

getDico(id: string, lang: string): Observable<DicoComponent> {

    if (id != null) {
        let singleSubject = this.subjects[id];

        if (!singleSubject) {
            this.ids.push(id);
            singleSubject = new Subject();
            this.subjects[id] = singleSubject;
        }
        return singleSubject.asObservable().share().take(1);
    }
}

sendRequest() {
    // Stuff to call the ASP Controller that calls the API 
    (...)        

    this.http.get(lControllerFullURL + lHttpRequestBody)
        .map((res: any) => res.json())
        .subscribe(data => {
            // Gestion du retour du WebService
            switch (data.status) {
                case "success":
                    let l_cRet: string = null;

                    // Response is looking like that : {"status":"success",
                    //                                  "results"://{"211800":"Compétences obligatoires",
                                                                   "211801":"Toutes les compétences"}}
                    for (l_cRet in data.results) {
                        let l_dicoID = l_cRet;                   // My DicoID
                        let l_dicoText = data.results[l_cRet];   // the text

                        if (!l_dicoText.includes("UNDEFINED")) {
                            // Trying to send the text to the corresponding dicoID here
                            this.subjects[l_dicoID].next(l_dicoText);
                        }
                        else {
                             (...)
                        }

                    }
                    break;
                (...)
            }
        });
}

N.B : I noticed two things :

  1. I have no error, but I need something more to update my dico texts
  2. I probably need to .complete() my observables but I don't really know when.

I'm quite a noob with RxJS, and I need more time to understand them so please be patient with me...

回答1:

I don't know what the problem is exactly, but I would change the component like

  @Component({
    selector: 'dico',
    template: `{{text | async}}`  
  })

  class Dico implements OnChanges {
    // Définition des paramètres et du texte en sortie
    @Input() private dicoID: string;
    @Input() private dicoLang: string;
    public text: Observable<String> = null;

    constructor(private dicoService: DicoService) {}

    ngOnChanges() {
      if(dicoId && dicoLang) {
        this.text = dicoService.getDico('211800', 'en');
      }
    }
  }

then you can use it with

<dico dicoID="211800" lang="en"></dico>

or