【问题标题】:Issue with angular 2 component not subscribing to observable in service in due time [duplicate]角度 2 组件未及时订阅可观察服务的问题 [重复]
【发布时间】:2016-09-10 16:04:55
【问题描述】:

我有一个组件应该从服务中检索数据。

这是我的组件:

@Component({
    templateUrl: 'app/dashboard/useraccount/firstname/useraccount-firstname.component.html',
    directives: [ROUTER_DIRECTIVES],
    pipes: [TranslatePipe]
})
export class UserAccountFirstNameComponent implements OnInit {

    currentUserAccount:Object;
    errorMessage:string;

    constructor(private userAccountService:UserAccountService) {
    }

    ngOnInit() {
        this.userAccountService.getCurrentUserAccount()
            .subscribe(
                param=> this.currentUserAccount = param,
                error => this.errorMessage = <any>error
            );
    }

    updateFirstName() {
        this.userAccountService.updateFirstName(this.currentUserAccount);
    }

}

这里是对应的服务:

@Injectable()
export class UserAccountService {

    constructor(private http:Http) {
    }

    getCurrentUserAccount():Observable<Object> {
        return this.http.get('/api/useraccount')
            .map(this.mapUserAccount)
            .catch(this.handleError);
    }

    updateFirstName(currentUserAccount) {
        this.http.patch('/api/useraccount/firstname/' + currentUserAccount.firstName, null);
    }

    private mapUserAccount(res:Response) {
        console.log(res.json());
        return res.json();
    }

    private handleError(error:any) {
        // In a real world app, we might use a remote logging infrastructure
        let errMsg = error.message || 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);
    }

下面是UserAccountService 的提供者:

bootstrap(MainComponent, [ROUTER_PROVIDERS,
    HTTP_PROVIDERS,
    TRANSLATE_PROVIDERS,
    SessionService,
    UserAccountService,
    TranslateService,
    provide(RequestOptions, {useClass: ApplicationRequestOptions}),
    provide(LocationStrategy, { useClass: HashLocationStrategy }),
    provide(TranslateLoader, {
        useFactory: (http:Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
        deps: [Http]
    })]);

这是模板中的相关部分:

<input type="text"
       ngControl="firstName"
       #firstName="ngForm"
       required
       minlength="2"
       maxlength="35"
       pattern_="FIRST_NAME_PATTERN"
       [(ngModel)]="currentUserAccount.firstName"
       placeholder="{{'FIRST_NAME_FORM.NEW_FIRST_NAME'| translate }}"
       class="form-control"/>

问题是,当模板被渲染时,currentUserAccount 在 ngModel 中仍然是 undefined...

有人可以帮忙吗?

附:我很困惑,因为我的用例(有一个组件调用使用 http 的服务方法)与此处提供的角度示例非常相似:http://plnkr.co/edit/DRoadzrAketh3g0dskpO?p=preview

【问题讨论】:

  • 这很难说,但您似乎在实例化后的任何时候都没有调用updateFirstName。此外,它需要异步处理。与您对ngOnInit 所做的相同。如果不是这样,我知道。
  • + updateFirstName 在你的服务中没有返回任何东西。
  • updateFirstName 在这里无关紧要。相关的是userAccountService.getCurrentUserAccount
  • 我可能一开始就不应该在此处包含 updateFirstName。

标签: angular angular2-services rxjs5


【解决方案1】:

Angular 已经在 ngOnInit() 之前解析了绑定。您只需调用对服务器的异步调用来获取最终会到达的数据(并执行您传递给this.userAccountService.getCurrentUserAccount().subscribe(...)的回调

为了避免当 Angular 绑定视图时 currentUserAccount 仍然是 null 时出现错误,您可以使用 Elvis 或安全导航运算符 ?. 进行父视图绑定 [] 但不能用于事件到-不支持父绑定 () (有讨论以添加对此的支持)您可以使用这种更详细的样式:

<input type="text"
       ngControl="firstName"
       #firstName="ngForm"
       required
       minlength="2"
       maxlength="35"
       pattern_="FIRST_NAME_PATTERN"
       [ngModel]="currentUserAccount?.firstName"
       (ngModelChange)="currentUserAccount ? currentUserAccount.firstName = $event : null"
       placeholder="{{'FIRST_NAME_FORM.NEW_FIRST_NAME'| translate }}"
       class="form-control"/>

【讨论】:

  • 非常感谢君特。我想知道是否有办法像 ng 1.x 路由器一样进行解析?
  • 对不起,我不太了解Ng1,尤其是路由器。它有什么作用?
  • 它在渲染路由之前解析promise(或observables)。也许像实现OnActivate 这样的东西可以帮助......
  • 我明白了。谢谢(你的)信息。 OnActivate 应该允许这样做,但是有一个未解决的问题是它不会等待解决 AFAIK 的承诺。一个简单的解决方法是将*ngIf="currentUserAccout" 添加到视图中的最外层元素。
猜你喜欢
  • 2021-11-26
  • 1970-01-01
  • 2018-02-22
  • 2016-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
  • 1970-01-01
相关资源
最近更新 更多