2016-05-02 5 views
1

Ich frage mich, was ist eine beste Möglichkeit, ein Formular nach Erhalt der Antwort vom Server zu laden. Ich habe Code geschrieben, wo er Daten vom Server bezieht, und in meiner Komponente abonniere ich die Antwort, aber Meine Benutzeroberfläche wird geladen, auch wenn ich die Antwort bekomme.Füllen Formular nach HTTP-Antwort in angular2

Ich möchte diese Komponente zum Hinzufügen und Bearbeiten verwenden.

Komponente:

@Component({ 
selector: 'gate', 
templateUrl: '/public/app/views/gate.html', 
directives: [GateFormComponent, StrategyComponent], 
providers : [MyService] 
}) 

export class MyComponent { 

private id:any; 

constructor(private _routeParams:RouteParams, @Inject(MyModel) private myModel, 
      private myService : MyService) { 
} 

ngOnInit() { 
    this.id = this._routeParams.get("id"); 
    if (this.id) { 
     this.gateDataModel.unique_display_id = parseInt(this.id); 
     this.myService.loadData(this.id) 
      .subscribe(response => console.log(response)); 
    } 
} 

In meiner Komponente, ich lade 2 Komponenten, von denen eine Form aufweist, in die ich habe Daten zu laden, sobald ich die Antwort. Und das alles sollte nur passieren, wenn ich eine ID zur Verfügung habe.

Service:

@Injectable() 
export class MyService extends HTTPServices { 

constructor(http:Http) { 
    super(http); 
} 


loadData(id:number) { 
    return this.query(url) 
     .map(res => res.json()) 
     .catch(this.handleError) 
} 


private handleError(error:Response) { 
    console.log("Error : ", error); 
    return Observable.throw(error.text()); 
} 

HTTPServices

export class HTTPServices { 

private headers:Headers; 
private http:Http; 

defaultOptionsArgs:RequestOptionsArgs; 

constructor(http:Http) { 
    this.http = http; 
    this.headers = new Headers(); 
    this.headers.append('Content-Type', 'application/json'); 
    this.defaultOptionsArgs = { 
     'headers': this.headers 
    }; 
} 



create(servicePath:string, model:any, options?:RequestOptionsArgs) { 
    var url = this.getUrl(servicePath); 
    var options = options ? options : this.defaultOptionsArgs; 
    return this.http.post(url, JSON.stringify(model), options); 
} 

query(servicePath:string, options?:RequestOptionsArgs) { 
    var options = options ? options : this.defaultOptionsArgs; 
    return this.http.get(servicePath, options); 
} 

} 

---- ----- Edited

Schließlich konnte ich @CanActivate hinzufügen und es ist Arbeiten.

@Component({ 
selector: 'gate', 
templateUrl: '/public/app/views/gate.html', 
directives: [ROUTER_DIRECTIVES, GateFormComponent, StrategyComponent] 
}) 

@CanActivate(
(next: ComponentInstruction, prev: ComponentInstruction) => { 
    return new Promise((resolve) => { 
     let id = next.params["id"]; 
     let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]); 
     let http = injector.get(Http); 
     if(id){ 
      http.get(URL) 
       .subscribe((response) => { 
        console.log(response) 
        next.routeData.data["response"] = response; 
        // continue 
        resolve(true); 
       }, (error) => { 
        resolve(false); 
       }); 
     } else { 
      resolve(true); 
     } 
    }); 
} 

) 

export class MyComponent{ 

private id:any; 

constructor(private _routeParams:RouteParams, @Inject(MyModel) private myModel, routeData: RouteData) { 
    console.log(routeData.get("response")); 
} 

} 

Die Komponente wird geladen und dann erhalte ich die Antwort

Dank

Antwort

0

In Sie Komponente, die Sie gerade

template: ` 
<div *ngIf="data"> 
    <!-- form goes here --> 
</div> 
` 

verwenden können, wo data eine Eigenschaft ist, die festgelegt ist auf einen Wert, wenn die Antwort vom Server eintraf.

+0

gehen wir nicht so etwas wie ngResource in Winkel 2 haben, wo ich den Anruf tätigen und die Benutzeroberfläche halten, bis ich die Antwort bekommen? – Anuteja

+0

Derzeit keine 'ngResource'. [CanActivate] (https://angular.io/docs/ts/latest/api/router/CanActivate-decorator.html) sollte in der Lage sein, das Routing zu verzögern, bis eine zurückgegebene 'Promise' aufgelöst ist, aber ich denke, das tut nicht ' t funktionieren derzeit richtig. Der Router wird sowieso überarbeitet. –

+0

AsyncRoute? https://angular.io/docs/js/latest/api/router/AsyncRoute-class.html oder vielleicht AsyncPipe? https://angular.io/docs/ts/latest/api/common/AsyncPipe-class.html – IgorL

0

Wenn Sie Angular2 Routing nutzen (und es scheint der Fall zu sein), könnten Sie nutzen die OnActivate Interface und seine routerOnActivate verwenden:

Definiert Strecke Lifecycle-Methode routerOnActivate, die durch den Router an die aufgerufen wird, Ende einer erfolgreichen Routennavigation.

Für die Navigation einer einzelnen Komponente wird abhängig vom Ergebnis von CanReuse nur OnActivate oder OnReuse aufgerufen.

Der routerOnActivate-Hook wird mit zwei ComponentInstructions als Parameter aufgerufen, wobei der erste die aktuelle Route darstellt und der zweite Parameter die vorherige Route oder Null darstellt.

Wenn routerOnActivate eine Zusage zurückgibt, wartet die Routenänderung, bis das Versprechen die Instantiierung und Aktivierung untergeordneter Komponenten veranlasst.

Sie könnten ein Versprechen zurückgeben, das gelöst wird, wenn Ihre Daten da sind.Hier ist ein Beispiel:

@Component({ ... }) 
export class MyComponent { 
    private id:any; 

    constructor(private _routeParams:RouteParams, 
       @Inject(MyModel) private myModel, 
       private myService : MyService) { 
    } 

    routerOnActivate() { 
    this.id = this._routeParams.get("id"); 
    return new Promise((resolve, reject) => { 
     if (this.id) { 
     this.gateDataModel.unique_display_id = parseInt(this.id); 
     this.myService.loadData(this.id) 
     .subscribe(response => { 
      console.log(response); 
      resolve(); 
     }); 
     } else { 
     resolve(); 
     } 
    }); 
    } 

    (...) 
} 
+0

Danke Thierry für die Antwort. Ich habe den gleichen Weg wie Sie vorgeschlagen implementiert, aber aus irgendeinem Grund werden meine Kindkomponenten geladen, noch bevor das Versprechen gelöst wurde. Ich habe die Frage bearbeitet, um zu sehen, was ich implementiert habe. – Anuteja

+0

können Sie das Kind mit DynamicComponentLoader laden? https://angular.io/docs/js/latest/api/core/DynamicComponentLoader-class.html – IgorL

0

ich eine ähnliche Frage hatte, aber da kann die Lösung auch für Ihre usecase verwendet werden, würde ich empfehlen, einen Blick auf die akzeptierte Antwort zu haben: How to manipulate a component on specific routes in Angular2

Die Grundidee ist, die router-outlet-Anweisung zu erweitern und die activate()-Funktion zu überschreiben, die aufgerufen wird, bevor die nächste Route aktiviert wird, und auf ein Versprechen wartet, das aufgelöst werden soll.

Zum Beispiel könnten Sie so etwas tun:

@Directive({ 
    selector: 'custom-router-outlet' 
}) 
export class CustomRouterOutlet extends RouterOutlet { 
    private parentRouter:Router; 

    constructor(_elementRef: ElementRef, 
      _loader: DynamicComponentLoader, 
      _parentRouter: Router, 
      @Attribute('name') nameAttr: string, 
      private _myRoutingService:MyRoutingService) { 
     super(_elementRef, _loader, _parentRouter, nameAttr); 
     this.parentRouter = _parentRouter; 
    } 

    activate(nextInstruction: ComponentInstruction): Promise<any> { 
     let someRouteSpecificData = nextInstruction.routeData.data['someRouteData']; 
     if(someRouteSpecificData) { 
      _myRoutingService.beforeRoute(someRouteSpecificData).subscribe(() => { 

       // go on after this has been resolved 
       return super.activate(nextInstruction); 

       // or maybe cancel the route: 
       return false; 

       // or maybe do something crazy: 
       nextInstruction.componentType = MyOtherComponent; 
       return super.activate(nextInstruction); 
      } 

     } 
     return super.activate(nextInstruction); 
    } 
} 

Ich glaube, Sie leicht diese für Ihre Zwecke ändern könnte. Sie können Ihre @RouteConfig zum Beispiel verwenden, um einige Informationen darüber zu erhalten, was bei einer Routenänderung passieren oder überprüft werden soll.

Ein anderer Ansatz wäre die Verwendung des @CanActivate Dekorators wie hier bereits erwähnt, aber es ist ein bisschen schwieriger zu erreichen. Es fühlt sich nur ein bisschen hacky an diesem Punkt. Ich könnte das später hinzufügen, wenn Sie interessiert sind.

+0

Ich denke, dass Ihr Fall am besten funktioniert, wenn ich mich um die Authentisierung kümmern muss und überprüfen muss, ob der Benutzer eine Sitzung hat oder nicht. Aber in meinem Szenario ist es nur in einem Fall, wo ich Daten vorladen möchte, d. H. Der Benutzer möchte das Formular bearbeiten, für das ich die Daten laden möchte, und dann die Benutzeroberfläche laden, sobald ich die Daten habe. CanActivate oder OnActivate wäre die beste Option für mich ab sofort, aber aus irgendeinem Grund 'OnActivate' funktioniert nicht für mich und mit '@ CanActivate' zu ​​arbeiten Ich brauche Zugriff auf' routeparams', um die ID für die herauszufinden Ich muss die Daten ziehen. – Anuteja

+0

Wahr, ich tat dies wegen Authentifizierung und Rollenprüfungen, aber auch für UI-Trigger abhängig von Routen. Z.B. Ich verwende dies, um anzugeben, ob eine Komponente beispielsweise eine Sidebar anzeigen soll. Was ich nicht verstehe, warum willst du diese Logik in deiner Komponente? Sie sagen, es ist nur ein Szenario, aber es scheint abhängig von Ihrer Route, so dass es sinnvoll wäre, das Standardverhalten des Routers für Ihre Bedürfnisse zu überschreiben und diese Konfiguration (routenspezifische Berechtigungen, ui configs usw.) an einem Ort zu haben ('@ RouteConfig')). Abgesehen davon, wo ist das Problem beim Zugriff auf routeParams, wenn Sie '@ CanActivate' verwenden? – lexith

+0

Ich habe versucht, '@ CanActivate' zu ​​verwenden, aber wie injiziere ich' RouteParams' hinein. Eine Möglichkeit, die ich ausprobiert habe, war, einen 'Injector' zu erstellen und' RouteParams' zu verwenden, was nicht funktionierte. Jede Hilfe dazu wäre willkommen. Bezogener Injektor-Code von [link] (http://plnkr.co/edit/Bim8OGO7oddxBaa26WzR?p=preview) – Anuteja