2017-10-06 1 views
0

Ich versuche einen bidirektionalen Dienst zu erhalten und kann nicht herausfinden, wo ich einen Schritt verpasse oder etwas falsch gemacht habe. Es gibt keine Fehler in der Konsole , aber es passiert nichts, wenn ich versuche, Daten über sie zu senden. (Here's) eine Plunker zu dem, was ich bisher habe.Bidirektionaler Dienst aktualisiert keine Daten in Angular 2

der Prozess I geht so

lädt diesen Körper von Daten zu erreichen bin versucht, in app.ts und iterieren mit input.copmonent.ts. (erfolgreich ausgeführt).

{ 
    "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" 
     } 

    ] 
} 

Laden Sie Daten in neue Variable und verwenden Sie ngModel in Vorlage, um Benutzerantwort zu aktualisieren. (done erfolgreich)

//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. 

Service erstellen, Daten empfangen von dem Response Variable in input.component.ts und zur Verfügung stellen für app.ts zu abonnieren. (erfolgreich getan .... Ich denke, ... zum größten Teil)

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

} 

erstellen Funktion in Input.component.ts Daten addResponse() Funktion in Dienst zu senden. (erfolgreich getan .... Ich denke)

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

} 

erstellen Abonnement FormList in app.ts. (Done erfolgreich)

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

Nach diesem Punkt alles Lasten erreichen bis fein ohne Fehler, aber wenn ich etwas in die Eingabefelder ein und klicken Sie senden, nichts zeigt sich in der Bindung I in der app.ts Vorlage gemacht zu zeigen, wenn ein neues Objekt zum Array hinzugefügt wird. Wenn ich verschiedene Methoden wie push() anstelle von next() versuche, erhalte ich Fehler, die mir this.FormList.push() is not a function sagen. Was muss ich tun, damit dies funktioniert?

Ich möchte auch darauf hinweisen, dass der Grund, warum ich "Daten kopieren" in der input.copmonent.ts Datei ist, weil in der realen Welt Nutzung dieser Qdata Variable wird viel mehr als nur 4 Eigenschaften, obwohl es nur Senden Sie diese 4 an die Response Variable, um zurück zur übergeordneten Komponente zu senden.

Von diesem Punkt vorwärts Ich plane, die FormData Variable zu verwenden, um eine Vorlage Driven Formular mit versteckten vorgefüllter Eingänge etwas zu wiederholen, wie dieser

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

Der Grund Ich versuche, es auf diese Weise zu tun ist, weil die Arten von Fragebögen, die ich mache, haben Tonnen von optionalen Fragen verschachtelt in Fragen für mehrere Stufen which you can see here. Ich hoffe, dass dies ein guter Weg ist, um die Antworten des Benutzers zu sammeln und sie alle an einem Ort ohne all die Kopfschmerzen zu platzieren. Solange der answer.service in den input.component importiert wird, wird er immer in der Lage sein, die Liste zu senden/zu aktualisieren, egal in welche Richtung der Benutzer geht und welchen Umstand die Eingaben erfordern. Was muss ich tun, um sicherzustellen, dass die answer.service für diesen Zweck liefern kann?

Antwort

1

Es gibt ein paar Probleme hier, ist die erste Frage, dass Ihre child component werden auch die answer service als Anbieter markiert werden, so dass es eine neue Instanz von AnswerService bekommt statt die gleiche Instanz des Dienstes als Mutter bekommen.

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

Auch die getter für Ihre FormList war falsch, ich schlage vor, mit diesem Ansatz, wie in den official example.

Ihr Service sollte so aussehen.

Jetzt auf Ihrem app.component müssen Sie wie so auf die Ereignisse abonnieren:

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

    // ... 
} 

Beachten Sie, dass im Abonnement I des FormData Array das Ergebnis bin anhängt. Der QuestionService Code benötigt wahrscheinlich etwas Nachbesserung, aber Sie bekommen die Idee.

Hier ist ein plunker arbeiten!

+1

JA DIESES FUNKTIONIERT !. Einzige Sache ist, ich verstehe nicht, warum die Daten nicht mit dem Objekt übergehen. – Optiq

+1

Behoben, das Problem ist in der 'sendResponse' Methode, ich werde die Antwort aktualisieren. Der Plünderer hat eine funktionierende Lösung. –

+0

Danke ich schätze es wirklich. Jetzt zu verstehen, warum das funktioniert lol. – Optiq

Verwandte Themen