Как я могу связать с обратным вызовом в Angular 4 - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь привязать мой шаблон к значению, которое было возвращено из подписки с помощью обратного вызова.Но обнаружение изменений не вызывается.

 //authorisation service
public login(data,callbackFromLogin : (msg) => void): void {
    this.http.httpPost(ApiRoutes.LoginRoute,data).subscribe(result => { 
        callbackFromLogin(msg);
    });
 }
 
 //and then in login component 
onSubmit(request) {
    this.authService.login(request,(message) => { 
        alert(NgZone.isInAngularZone());
        if(message) {
            this.ngZone.run( () => { 
                this.message = message;
                alert(NgZone.isInAngularZone());
            });  
         }   
     });
}
<div>{{message}}</div>

Сообщение не изменяется, хотя и получает значение от службы.Я думаю, что эта проблема связана с Зоной.

Ответы [ 6 ]

0 голосов
/ 23 ноября 2018

Я нашел проблему.В моем AuthService, в функции login (), которая возвращает Observable, я делаю вызов this.routeAfterLogin (false).Эта функция перенаправляет мой маршрут на страницу входа в случае возникновения ошибки.Это перенаправление внутри наблюдаемого портит обнаружение изменений.На самом деле мне это не нужно, после удаления все стало работать нормально.Спасибо всем за помощь.

 public login(data): Observable<any> {
    return this.rHttp.post(ApiRoutes.LoginRoute,data).pipe(map(result=>{ 
      if(...){
      // not relevant
      }else{ 
        let msg = "error message";
        this.alertService.error(msg);
        **this.routeAfterLogin(false);**
        this.messageService.sendMessage('',Events.UserLogout);
        return {msg:msg};
      }
    }));
}

**private routeAfterLogin(state:boolean)** {
  this.userIsLoggedIn = state;
  if(this.userIsLoggedIn){
    this.router.navigate(['/home']);
    console.log("Login");
  } else {
    this.router.navigate(['/login']);
    console.log("Failure Login");
  }
}
0 голосов
/ 23 ноября 2018

Я думаю, что это проблема, связанная с Зоной, как вы предложили ... в этом случае:

 onSubmit(request){
    this.message="outer message"
    this.loginRequest = this.authService.login(request);
    this.loginRequest.subscribe((result) => {
      if(result.msg){
        this.message ="inner message"
       // alert(this.message)
      }   
    });
  }

Когда срабатывает onSubmit (), я вижу привязку «внешнего сообщения», но после входа в подписку она исчезает и «внутреннее сообщение» вообще не отображается.

0 голосов
/ 23 ноября 2018

Да .. есть AuthService:

import { SessionService } from '../session/session.service';
import { environment } from './../../../environments/environment';
import { IUser, UserType } from '../../../../../contracts/IUser';
import { IEmployee } from '../../../../../contracts/IEmployee';
import { Injectable,Inject } from '@angular/core';
import { Router } from '@angular/router';
import 'rxjs/add/operator/filter';
import * as auth0 from 'auth0-js';
import { Http } from '@angular/http';
import {ReplaySubject, Observable} from 'rxjs/Rx'; 
import { ApiService } from '../api/api.service';
import { ActivityService } from '../activity/activity.service';
import { UserActivityAction } from '../../../../../contracts/Library';
import { ApiRoutes } from '../../../../../contracts/ApiRoutes';
import { AlertService} from '../alert/alert.service';
import { MessageService} from '../message/message.service';
import {Events} from '../../../../../contracts/Library';
import { map } from 'rxjs/operators';

@Injectable()
export class AuthService {
  private userIsLoggedIn : boolean;
  
  constructor(public http: ApiService,private rHttp: Http,
              private session:SessionService,
              @Inject('BASE_URL') public baseUrl: string,
              public router: Router,
              private alertService: AlertService,
              private activity: ActivityService,
              private messageService : MessageService) 
  {
    this.session = session;
  }


 // logIn attempts to log in a user
 handleAuthentication() : void {
    let auth = this.http.httpGetAll(ApiRoutes.AuthRoute);
    
    auth.subscribe(
      data => {
         let results = data.json();
         switch(results.status) { 
          case 401: { 
            this.routeAfterLogin(false);
            this.messageService.sendMessage('',Events.UserLogout);
            break; 
          } 
          case 402: { 
            break; 
          } 
          case 200: { 
            //when success
            break; 
          } 
          default: { 
            this.routeAfterLogin(false);
            break; 
          } 
       } 
      },
      error => {
        console.log(error);
    });
    this.router.navigate(['/home']);
  }
  
  public login(data): Observable<any> {
    return this.http.httpPost(ApiRoutes.LoginRoute,data).pipe(map(result=>{
      if (result && result.status == 200) {
     //when success
      }else{ 
        let msg = "some error message";
        this.routeAfterLogin(false);
        return {msg:msg};
      }
    }));
  }

  private routeAfterLogin(state:boolean) {
    this.userIsLoggedIn = state;
    if(this.userIsLoggedIn){
      this.router.navigate(['/home']);
      console.log("Login");
    } else {
      this.router.navigate(['/login']);
      console.log("Failure Login");
    }
  }

  public logout(): void {
    let auth = this.http.httpGetAll(ApiRoutes.LogoutRoute);
    auth.subscribe(
      data => {
        console.log("Logout");
        this.messageService.sendMessage('',Events.UserLogout);
        this.router.navigate(['/login']);
      },
      error => {
        console.log(error);
    });
  }

 public isAuthenticated(): boolean {
   return this.userIsLoggedIn;
 }

 public fillFileDownloadPass(){
  let getUploadPath$ = this.http.httpGetAll(ApiRoutes.DownloaPathdRout);
    
  getUploadPath$.subscribe(
    data => {
       let results = data.json();
       switch(results.status) { 
        case 200: { 
          this.session.download101AtchFilePath = results.filehDownloadPat;
          this.session.approvedFormsPath       = results.approvedFormsPath;
          break; 
        } 
        case 400: { 
          console.log("didn't find an upload path");
          break; 
        } 
        default: { 
          break; 
        } 
     } 
    },
    error => {
      console.log(error);
  });
 }
}

Функция handleAuthentication () вызывается из app.component ..

 ngOnInit() {
    this.authService.handleAuthentication();
    this.subscription = this.messageService.getMessage().subscribe(message => { 
      switch (message.type) {
        case Events.UserLogin:
          this.showNav = true;
          break;
        case Events.UserLogout:
          this.showNav = false;
          break;  
        case Events.FirstEntrance :  
         //some message
         break;
      } 
    }); 
 }

Функция httpPost ApiService оборачивает http:

 httpPost(url:string,data:any):Observable<Response | any> {
      return this._http.post(`${this.baseUrl}${url}`, data )
          .map(this.parseData)
          .catch(this.handleError.bind(this));
 }

private parseData(res: Response)  {
    return res.json() || [];
}
0 голосов
/ 23 ноября 2018

Попробуйте и дайте мне знать.

  1. Создайте собственность loginRequest: Observable<any>;
  2. Внутри onSubmit():

onSubmit(request){ this.loginRequest = this.authService.login(request); }

В вашем шаблоне

<div> 
  {{ (loginRequest | async)?.msg }}
</div>

Вот простой вызов Http.

import {HttpClient} from '@angular/common/http';

class SomeService {
  constructor(private _http: HttpClient){}

  postSomething() {
    return this._http.post('url', toPost);
  }
}
0 голосов
/ 23 ноября 2018

Я воспользовался вашим советом и изменил свой код на это:

//Service

public login(data): Observable<any> {
    return this.http.httpPost(ApiRoutes.LoginRoute,data).pipe(map(result=>{
      if (result && result.status == 200) {
      ///
      }else{
        let msg = `my message`;
        return {msg:msg};
      }
    }));
  }
  
  //login component
  onSubmit(request){
    this.authService.login(request).subscribe((result) => {
      if(result.msg){
        this.message = result.msg;
        alert( this.message )
      }   
    });
  }
<div>{{message}}</div>

Та же проблема, сообщение передается в результат, когда я вызываю функцию alert (this.message), сообщение показывается выше ... но естьОднако в шаблоне нет изменений.

0 голосов
/ 23 ноября 2018

Я не знаю точно, почему этого не происходит.

Но некоторые вопросы ниже.

Кто задает msg для обратного вызова?

Может быть, вы хотитесделать callbackFromLogin(result);?

Но я думаю, что вы могли бы попытаться реализовать другое решение.

Почему вы передаете обратный вызов службе, а не выполняете функцию внутри подписки на компоненте?

Примерно так:

 // authorisation service
 public login(data) {
  return this.http.httpPost(ApiRoutes.LoginRoute, data);
  // if you want manipulate the message you could use `pipe` method here
 }

 // and then in login component 
 onSubmit(request) {
   this.authService.login().subscribe((message) => {
     if(message){
       this.message = message;
     }   
   });
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...