2016-11-18 2 views
0

Wenn ich versuchte, mit 'this.atoms' in den searchAtoms auf Atome zuzugreifen, gibt es "TypeError: Kann Eigenschaft 'length' von undefined nicht lesen". Ich denke Atome sind alle gesetzt, weil * ngFor gut funktioniert. Es gibt eine versteckte Logik hinter subscribe? Wenn jemand davon weiß, könnten Sie einige Hinweise geben? Und, noch eine Frage, wenn ich getAtoms Methode mit einem Parameter definiert, Atom Name Wert aus Eingabefeld in der atom.service.ts wie this.service.getAtoms (newAtom) erhalten. Aber ich bekomme "Ein Parameter-Wert ist nur in einer Konstruktor-Implementierung erlaubt". Ich denke, ich kann diesen Weg nicht benutzen. Kann Ihnen irgendjemand einen wünschenswerten Weg empfehlen?Wie kann man auf Objekte zugreifen, die vom Dienst in der Komponente abgerufen wurden?

app.component.ts

import {Component} from 'angular2/core'; 
import {Router} from 'angular2/router'; 
import {AtomService} from './service/atom.service'; 
import {Atom} from './datatype/Atom'; 

@Component({ 
    selector: 'my-app', 
    template: `<br> 
    <input #atomname value='atom1'> 
    <button (click)=searchAtoms(atomname.value)>Search Atoms</button> 
    <br><br> 
    <ul> 
     <li *ngFor="#atom of atoms"> 
      {{atom.id}} - {{atom.name}} 
     </li> 
    </ul>`, 
    providers: [ConceptService] 
}) 


export class AppComponent { 

    atoms: Array<Atom>; 

    constructor(private service : AtomService) { 

    } 

    searchAtoms(newAtom: string) { 
     console.log("searchAtoms\t" + newAtom); 
     if (newAtom) { 
      this.service.getAtoms(newAtom).subscribe(data => this.atoms = data); 
      console.log(this.atoms.length); 
     } 
    } 
} 

atom.service.ts

import { Injectable }  from 'angular2/core'; 
import { Http, Response, URLSearchParams, Headers } from 'angular2/http'; 
import 'rxjs/add/operator/map'; 
import {Atom} from '../datatype/Atom'; 

@Injectable() 
export class ConceptService { 

    constructor(private http: Http) { 
    this.http = http; 
    } 

    getAtoms(private newAtom: string) { 
    return this.http.get('api/atoms.js') 
    .map((responseData) => {return responseData.json()}) 
    .map(data => { 
     let results:Array<Atom> = []; 
     for (var i = 0; i < data.result.length; i++) { 
      results.push(new Atom(data.result[i].id, data.result[i].name)); 
     } 
     return results; 
    }); 
    } 
} 

Antwort

2

Der Http Dienst gibt ein Observable und Sie abonnieren Sie es. Dies ist ein asynchroner Vorgang, aber Sie versuchen, auf die Daten zuzugreifen, bevor sie vom Server eintreffen. Wenn Sie Ihren console.log innerhalb Ihres subscribe Rückrufs verschieben, wird es funktionieren.

this.service.getAtoms(newAtom).subscribe(data => { 
    this.atoms = data; 
    console.log(this.atoms.length); 
}); 

Für Ihre zweite Frage müssen Sie nur das Schlüsselwort private löschen.

getAtoms(newAtom: string) { } 
+0

Vielen Dank, es funktioniert gut. –

+0

Zusätzliche Frage, :) Gibt es trotzdem ich kann die Methode innerhalb abonnieren? Ich habe es getestet, indem ich console.log (this.atoms.length) als eine andere Methode namens printTest() definiert habe. Ich konnte printTest nicht aufrufen, es heißt "ReferenceError: printTest() ist nicht definiert". Ich denke, es macht Sinn. Letztendlich möchte ich diese Atome paginieren, also brauche ich einige Manipulationen am Atomarray. Eigentlich denke ich, eine begrenzte Anzahl von Atomen zu trennen, indem ich sie an den Paging-Dienst (paging.service.ts) delegiere. Haben Sie Empfehlungen für diese Aufgabe? Ich weiß es wirklich wieder zu schätzen. –

+0

Hast du es so genannt 'this.printTest()'? Es sollte funktionieren. Aber ja, ich würde Ihnen empfehlen, die Paginierungslogik in einen Dienst zu verschieben. – Puigcerber

Verwandte Themen