2017-04-23 32 views
0

尝试更新组件之间的HTML元素使用角度服务似乎不适用于我。异步调用更新HTML元素,虽然角4.x服务

这不是How do I return the response from an asynchronous call?的重复。

全部项目:https://github.com/flamusdiu/micro-blog/tree/dev

我有这样的服务:

import { ElementRef, Injectable } from '@angular/core'; 
import { MdSidenav } from '@angular/material'; 
import { AsyncSubject } from 'rxjs/AsyncSubject '; 

import { Article } from '../models/article'; 

@Injectable() 
export class InterModuleService { 
    private _article: AsyncSubject <Article> = new AsyncSubject();  
    public sidenav: MdSidenav; 
    public sidenavToc: ElementRef; 
} 

我已经把我的观察到这里。可观察的是通过一个角度解析器填充我的路线。该组件设置为:

import { Component, Input, OnInit } from '@angular/core'; 
import { ActivatedRoute } from '@angular/router'; 

import { Article } from '../../models/article'; 
import { InterModuleService } from '../../service/inter-module.service'; 

@Component({ 
    selector: 'app-article-detail', 
    templateUrl: './article-detail.component.html', 
    styleUrls: ['./article-detail.component.css'] 
}) 
export class ArticleDetailComponent implements OnInit { 

    private article: Article; 

    constructor(private route: ActivatedRoute, private interModuleService: InterModuleService) { } 

    ngOnInit(): void { 
    this.route.data 
     .subscribe((data: { article: Article }) => { 
      this.interModuleService.article.next(data.article); 
     }); 

    this.interModuleService.article 
     .subscribe((data) => { 
      this.article = data; 
      this.interModuleService.sidenavToc.nativeElement['innerHTML'] = data.toc; 
     }); 
    } 
} 

我得到这是某种异步问题。我得到更新视图的文章数据。然而,任何文章对象的属性总是“未定义”或“空”在任何时候阅读,这使我的事情我的方法试图做到这一点是不完全正确的。


如果我加入一些console.logs这样的:

this.interModuleService.article.take(1) 
     .subscribe((data) => { 
      this.article = data; 
      console.log(this.article); 
      console.log(this.article.toc); 
      this.interModuleService.sidenavToc.nativeElement['innerHTML'] = data.toc; 
     }); 

我得到后续的截图(忽略HTML格式问题):

screencap of issue


刚供参考:article.tocarticle.attachments['toc']['data']的简写。但是,直接引用此结果会得到与上面相同的结果。 article.attachments['toc']有数据,但调用时属性data未定义。


BehaviorSubject更改为AsyncSubject,因为我只有真正关心发出的最后一个。可能不应该暴露主题,但没有看到不这样做的好方法。虽然data.toc仍未定义。 =(

+0

请给出[MCVE];那些未定义的地方在哪里出现,以及这是如何在模板中呈现的? – jonrsharpe

+0

'this.interModuleService.sidenavToc。nativeElement ['innerHTML'] = data.toc'总是'未定义',只是将'undefined'推送给模板。现在,'data'不是未定义的,并且包含当然的信息。 – flamusdiu

+0

您是否在回调中记录了“数据”?或者在之前的订阅中从中提取'.article'? – jonrsharpe

回答

0

我不得不移动整个异步过程,让附件更接近我出于某种原因需要它的地方,但我仍然不确定这样做的原因,然后与Async过程解决方法有关预计可能出现在任何点的值需要被占

这里是工作代码:

-module.service.ts间

import { ElementRef, Injectable } from '@angular/core'; 
import { MdSidenav } from '@angular/material'; 
import { AsyncSubject } from 'rxjs/AsyncSubject'; 

import { Article } from '../models/article'; 

@Injectable() 
export class InterModuleService { 
    public article: AsyncSubject<Article> = new AsyncSubject(); 

    public sidenav: MdSidenav; 
    public sidenavToc: ElementRef; 
} 

物品detail.component.ts

import { Component, Input, OnInit } from '@angular/core'; 
import { ActivatedRoute } from '@angular/router'; 

import { Article } from '../../models/article'; 

import { ArticleStore } from '../../state/ArticleStore'; 
import { InterModuleService } from '../../service/inter-module.service'; 

@Component({ 
    selector: 'app-article-detail', 
    templateUrl: './article-detail.component.html', 
    styleUrls: ['./article-detail.component.css'] 
}) 
export class ArticleDetailComponent implements OnInit { 

    private article: Article; 

    constructor(private route: ActivatedRoute, 
       private articleStore: ArticleStore, 
       private interModuleService: InterModuleService) { } 

    ngOnInit(): void { 
    this.interModuleService.article 
     .subscribe((data) => { 
      this.article = data; 

      Promise.all(Object.keys(this.article['attachments']).map((at) => { 
       return this.articleStore.getAttachment(this.article['id'],at).then ((res) => { 
        this.article.attachments[at]['data'] = res.toString(); 
       }) 
      })).then(()=> { 
       this.interModuleService.sidenavToc.nativeElement['innerHTML'] = this.article.attachments['toc'].data; 
      }); 

     }); 
    this.route.data 
     .subscribe((data: { article: Article }) => { 
      this.interModuleService.article.next(data.article); 
      this.interModuleService.article.complete(); 
     }); 
    } 
} 

物品detail.resolver.ts

import { Injectable } from '@angular/core'; 
import { Router, Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router'; 
import { Article } from '../../models/article'; 
import { ArticleStore } from '../../state/ArticleStore'; 


@Injectable() 
export class ArticleDetailResolver implements Resolve<Article> { 

    constructor(private articleStore: ArticleStore, private router: Router) {} 

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Article> { 

    let id = route.params['id']; 

    return this.articleStore.getArticle(id).then(article => { 
     if (article) { 
     return new Article(article); 

     } else { // id not found 
     this.router.navigate(['/articles']); 
     return null; 
     } 
    }); 
    } 
}