简体   繁体   English

如何从Angular 4中的回调绑定

[英]How can I bind from a callback in Angular 4

I am trying to bind my template to the value which was returned from subscription via callback. 我正在尝试将模板绑定到通过回调从订阅返回的值。 But there is no change detection invoked. 但是没有调用变更检测。

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

The message does not change, though It gets a value from a service. 该消息不会更改,尽管它会从服务获取值。 I guess this issue is related to Zone. 我想这个问题与区域有关。

I don't know exactly why this not happen. 我不知道为什么不会这样。

But some question below. 但是下面有一些问题。

Who is set msg to the callback? 谁将msg设置为回调?

Maybe you want to do callbackFromLogin(result); 也许你想做callbackFromLogin(result); ?

But I think you could try to implement another solution. 但是我认为您可以尝试实施另一种解决方案。

Why you are pass a callback to service and not do the function inside the subscription on the component? 为什么您将回调传递给service而不在组件的订阅内部执行该函数?

Something like this: 像这样:

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

I used your advise and change my code to this: 我使用了您的建议并将代码更改为此:

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

Same issue , the message is passed to result ,when I call to alert( this.message ) function , the message is shown above..but there is no change in a template Interpolation however. 同样的问题,消息传递给结果,当我调用alert(this.message)函数时,消息显示在上方。但是模板插值没有变化。

Try this and let me know. 试试这个,让我知道。

  1. Make a property loginRequest: Observable<any>; 设置属性loginRequest: Observable<any>;
  2. Inside onSubmit() : onSubmit()内部:

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

In your template, 在您的模板中

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

Here's a simple Http call. 这是一个简单的Http调用。

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

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

  postSomething() {
    return this._http.post('url', toPost);
  }
}

Yes..here is an AuthService: 是的。这里是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); }); } } 

The handleAuthentication() function is called from the app.component.. 从app.component。中调用handleAuthentication()函数。

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

The ApiService's httpPost function wraps the http: ApiService的httpPost函数包装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() || []; } 

I think it is a Zone related issue as you suggested..in that case: 我认为这是您建议的与区域相关的问题。在这种情况下:

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

When onSubmit() fires , I see the "outer message" binding , but after entrance to subscription it disappears and the "inner message" is not shown at all. 当onSubmit()触发时,我看到“外部消息”绑定,但是进入订阅后它消失了,并且“内部消息”根本没有显示。

I found the problem. 我发现了问题。 In my AuthService, in login() function, which returns an Observable, I am making a call for a this.routeAfterLogin(false) . 在我的AuthService中,在login()函数中返回一个Observable,我正在调用this.routeAfterLogin(false)。 This function redirects my route to login page in case the error occurs. 如果发生错误,此功能会将我的路线重定向到登录页面。 That redirection inside an observable messes the change detection. 可观察内部的重定向使更改检测变得混乱。 Actually I don't need it ,after removing it everything started to work fine. 实际上,我不需要它,将其删除后一切都可以正常工作。 Thanks all for the help. 谢谢大家的帮助。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Angular5效果中从回调返回? - How can I return from a callback in an Angular5 effect? 如何将日期选择器中的值绑定到angular2模型? - How can I bind a value from a datepicker to an angular2 model? 如何在 angular 中绑定锚标签 - How can i bind a anchor tag in angular 如何从回调函数使用ngrx / angular5从效果返回? - How can I return from an effect with ngrx / angular5 from a callback function? 如何绑定Angular Select中* ngFor项目的对象ID? 目前,select绑定与插值do的值相同。 - How can I bind object id from *ngFor item in Angular Select? At the moment, the select bind the same value as interpolation do. 如何从JSON中读取数据并将其绑定到Angular 2+中的Select下拉列表 - How can I read and bind data from this JSON to a Select dropdown in Angular 2+ 如何将数据绑定到在Angular 2中从父窗口打开的子窗口? - How can i bind data to child window opened from parent window in Angular 2? 角度2 | 我无法绑定其他课程的财产 - Angular 2 | I can't Bind property from another class 如何使用反应式表单将表单绑定到 Angular 6 中的模型? - How can I bind a form to a model in Angular 6 using reactive forms? 如何在 angular 2 中的 1 个属性绑定中绑定 2 个变量? - How can I bind 2 variables inside 1 property binding in angular 2?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM