2017-10-06 1 views
0

J'essaie de faire fonctionner un service bidirectionnel et je n'arrive pas à comprendre où il me manque une étape et où j'ai fait quelque chose de mal. , mais rien ne se passe lorsque je tente d'envoyer des données à travers elle. (Here's) un plunker à ce que j'ai jusqu'à présent.Le service bidirectionnel ne met pas à jour les données dans Angular 2

Le processus que je suis en train d'accomplir va comme ceci

charge cet ensemble de données dans app.ts et itérer avec input.copmonent.ts(fait avec succès)

{ 
    "questions":[ 
     { 
     "question": "How tall are you?", 
     "name": "height", 
     "id": "heightCtrl", 
     "template": "smInput" 
     }, 
     { 
     "question": "What is your favorite color?", 
     "name": "color", 
     "id": "colorCtrl", 
     "template": "smInput" 
     }, 
     { 
     "question": "What kind of car do you drive?", 
     "name": "car", 
     "id": "carCtrl", 
     "template": "smInput" 
     } 

    ] 
} 

Charger les données dans une nouvelle variable et utiliser ngModel dans le modèle pour mettre à jour la réponse de l'utilisateur. (fait avec succès)

//Input Component (omitted for relevance) 

@Component({ 
    template:` 
      <ng-container *ngIf="Qdata.template == 'smInput'"> 


       <p>{{Qdata.question}}</p> 

       <input type="text" 
        id="Qdata.id" 
        name="Qdata.name" 
        [(ngModel)]="Response.response" 
       > 


      </ng-container> 
      ` 
}) 

export class InputComponent implements OnInit{  

    @Input() Qdata: any;  //from app.ts 

    Response: FormResponse={}; // new variable 

    ngOnInit(){ this.prepResponse(); } 

    prepResponse(){ 
     let a = this.Qdata; 
     let b = this.Response; 

     b.question = a.question; 
     b.id = a.id; 
     b.name = a.name; 
    } 
} 



// Note: FormResponse is a custom class I made that's shaped the same as 
// the json data with the addition of a "response:string='';" field. 

Créer un service pour recevoir des données de la variable Response dans input.component.ts et mettre à la disposition app.ts abonner. (fait avec succès .... Je pense que ... pour la plupart)

//Imports Observable and Subject from proper places 

@Injectable() 

export class AnswerService { 

    private FormList = new Subject<FormResponse[]>(); // so far I think this is contributing 
                 to the problem somehow. 

    addResponse(data:FormResponse){ 
    this.FormList.next(data); 
    } 

    getFormList(): Observable<FormResponse[]>{ 
    return this.FormList.asObservable(); 
    } 

} 

Créer fonction Input.component.ts pour envoyer des données à addResponse() fonction en service. (fait .... Je pense avec succès)

import { AnswerService } from './answer.service'; 

@Component({ 
    template:` 
     <ng-container *ngIf="Qdata.template == 'smInput'"> 
      <!--previous HTML --> 

      <button (click)="sendResponse()">send</button> 
      <!-- plan to ultimately use OnChanges, using this to test --> 

     </ng-container> 
     `, 
    providers: [AnswerService] 
}) 

export class InputComponent implements OnInit{  

    @Input() Qdata: any; 

    Response: FormResponse={}; 


    constructor(private _ans : AnswerService) {} 

    ngOnInit(){ ... } prepResponse(){...} 

    sendResponse(): void{ 
     let a = this.Response; 
     let grp = new FormResponse({ 
      question:a.question, 
      response:a.response, 
      id:a.id, 
      name:a.name 
     }); 

     this._ans.addResponse(grp); 
    } 

} 

Créer un abonnement à FormList en app.ts. (Fait avec succès)

//app.ts (omitted for relevance) 

import { AnswerService } from './answer.service'; 

@Component({ 
    providers: [ AnswerService ] 
}) 

export class App implements OnInit{ 

    FormData: Array<FormResponse>=[]; 

    constructor(private _ans : AnswerService){} 

    ngOnInit(){ 
     this._ans.getFormList().subscribe(list => { list = this.FormData; }); 
    } 
} 

Après avoir atteint ce point de tout charge jusqu'à fin sans erreur, mais quand je tape quelque chose dans les champs de saisie et cliquez sur envoyer, rien ne montre dans la liaison que j'ai fait dans le modèle app.ts pour montrer lorsqu'un nouvel objet est ajouté au tableau. Lorsque j'essaie différentes méthodes, telles que push() au lieu de next() je reçois des erreurs en me disant this.FormList.push() is not a function. Que dois-je faire pour que cela fonctionne?

Je tiens également à souligner que la raison pour laquelle je suis "copier des données" dans le fichier input.copmonent.ts est parce que dans l'utilisation du monde réel de la variable Qdata aura beaucoup plus que seulement 4 propriétés, mais il sera seulement envoie ces 4 à la variable Response pour renvoyer au composant parent.

De ce point avant que je prévois d'utiliser la variable FormData pour itérer un modèle de formulaire Driven avec pré-rempli entrées quelque chose comme ça

<form #myForm="ngForm"> 

    <div *ngFor="let a of FormData"> 

     <div [attr.data-blank]="a.id" class="form-group"> 
     <!-- To force Angular to iterate a wrapper for each group --> 

      <input type="hidden" class="form-control" 
       [attr.name]="a.id" [(ngModel)]="a.question" 
      > 

      <input type="hidden" class="form-control" 
       [attr.name]="a.name" [(ngModel)]="a.response" 
      > 
     </div> 

    </div> 

</form> 

cachés La raison pour laquelle je suis en train de le faire de cette façon parce que les types de questionnaires que je fais ont des tonnes de questions facultatives imbriquées dans des questions pour plusieurs niveaux which you can see here. J'espère que ce sera un bon moyen de recueillir les réponses de l'utilisateur et les mettre tous dans un seul endroit sans tous les maux de tête. Tant que le answer.service est importé dans le input.component, il sera toujours en mesure d'envoyer/mettre à jour la liste, peu importe la direction de l'utilisateur et les circonstances des entrées dont il a besoin. Que dois-je faire pour m'assurer que le answer.service peut fournir pour cet usage?

Répondre

1

Il y a quelques problèmes ici, la première question est que votre child component faiblit aussi le answer service en tant que fournisseur, il obtient une nouvelle instance de AnswerService au lieu d'obtenir la même instance du service en tant que parent.

@Component({ 
    selector: 'input-component', 
    templateUrl: 'src/input.component.html' 
    // No providers 
}) 
export class InputComponent implements OnInit{ 

    // ... 

    /** Gets same instance of AnswerService as the parent component */ 
    constructor(private _ans: AnswerService){} 

    sendResponse(): void{ 
    this._ans.addResponse(this.Response); 
    }  
} 

En outre, le getter pour votre FormList était incorrecte, je suggère d'utiliser cette approche comme dans le official example.

Votre service devrait ressembler à ceci.

maintenant sur votre app.component vous devez vous abonner aux événements comme ceci:

@Component({ 
    selector: 'my-app', 
    templateUrl:'src/app.html', 
    providers: [ QuestionService, AnswerService ] 
}) 
export class App implements OnInit{ 

    FormData: FormResponse[] = []; 

    // ... 

    answerSubscription = this._ans.FormList.subscribe(a => { 
    console.log('gets here '+JSON.stringify(a, null, '\t')) 
    this.FormData.push(a) 
    }) 

    // ... 
} 

Notez que dans l'abonnement j'annexant le résultat au tableau FormData. Le code QuestionService a probablement besoin d'être retouché mais vous avez l'idée.

Voici un plunker qui fonctionne!

+1

OUI Cela fonctionne! La seule chose est que je ne comprends pas pourquoi les données ne passent pas avec l'objet. – Optiq

+1

Correction, le problème est dans la méthode 'sendResponse', je vais mettre à jour la réponse. Le plongeur a une solution de travail. –

+0

Merci, je l'apprécie vraiment. Maintenant, pour comprendre pourquoi cela fonctionne lol. – Optiq