尝试在组件之间更新HTML元素使用角度服务似乎对我不起作用。
这不是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;
}
我把我的观察放在这里。通过Angular Resolver为我的路线填充可观测量。该组件设置为:
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.log:
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格式问题):
仅供参考:article.toc
是article.attachments['toc']['data']
的简写。但是,直接引用它会产生与上面相同的结果。 article.attachments['toc']
有数据,但调用时属性data
未定义。
从BehaviorSubject
更改为AsyncSubject
,因为我只关心最后发出的一个。可能不应该暴露主题,但没有看到不这样做的好方法。虽然data.toc
仍未定义。 =(
答案 0 :(得分: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;
}
});
}
}