angular - 如何从不同的来源设置我的界面对象的值
问题描述
我有一个包含以下项目的 json 文件:
[
{"id": 1, "fileName": "1.txt", "title": "First Kidney Transplant in the Region"},
{"id": 2, "fileName": "2.txt", "title": "Another article"}
]
我有一个带有以下对象的接口 INewsArticle[]
export interface INewsArticles{
id : number,
fileName : string,
title : string,
content : Text
}
除了内容之外的所有内容都是从我的 json 文件中加载的。我想要做的是使用一个订阅从 .txt 文件中获取每篇文章的相应内容,我不知道如何在打字稿中做到这一点。
这是我的订阅代码:this.svcNewsArticles.LoadArticles().subscribe(data => this._newsArticles = data);
这是我的服务:
private _srcArticles : string = "./assets/news-articles/newsList.json";
constructor(private http:HttpClient) { }
LoadArticles() : Observable<INewsArticles[]>{
return this.http.get<INewsArticles[]>(this._srcArticles);
}
我目前拥有的是获取我的 INewsArticles[],使用 *ngFor 将其绑定到 HTML,然后调用另一个方法来订阅另一个请求,以使用 INewsArticles[].fileName 的参数从我的内容目录加载内容。但这在控制台上测试时会导致无限循环。
这是我的 HTML:
<div id="divContainer" class="container" fxLayout="row wrap" fxLayout.lt-md="column" fxLayoutAlign="center" fxLayoutGap="20px" [style.marginTop.%]="_marginTop">
<div id="divHeader" [fxHide]="_hideHeader">
<h1>What's New?</h1>
</div>
<mat-card fxFlex.gt-sm="30%" fxFlex.lt-md="95%" *ngFor = "let article of _newsArticles">
<mat-card-header>
<mat-card-title>
{{ article.title }}
</mat-card-title>
</mat-card-header>
<mat-card-content class="scrollable">
{{ getContent(article.fileName) }}
<!-- <embed src='../../../../assets/news-articles/content/{{ article.fileName }}'> -->
<!-- {{ getContent() }} -->
</mat-card-content>
</mat-card>
</div>
这是我的订阅:
getContent(fileName : string){
this.svcNewsArticles.GetContent(fileName).subscribe(data => {console.log(data)}, err => {console.log(err)});
}
这是我的服务:
GetContent(fileName : String){
return this.http.get('./assets/news-articles/content/'+fileName, {responseType : 'text'});
}
我是新手,请与我裸露。
解决方案
您可以使用任何高阶映射运算符(例如 switchMap 或 mergeMap)同时执行这两个 HTML 请求。
像这样的东西:
posts$ = this.http.get<Post[]>(this.postUrl).pipe(
mergeMap(posts =>
forkJoin(
posts.map(post =>
this.http.get<User>(`${this.userUrl}/${post.userId}`).pipe(
map(user => ({
title: post.title,
userName: user.name
}))
)
)
)
)
);
你可以在这里找到一个有效的 Stackblitz:https ://stackblitz.com/edit/angular-simple-posts-user-mergemap-deborahk
将其应用于您的代码,它看起来像这样:
this.http.get<INewsArticles[]>(this._srcArticles).pipe(
mergeMap(articles=>
forkJoin(
articles.map(article=>
this.http.get('./assets/news-articles/content/'+article.fileName, {responseType : 'text'}).pipe(
map(content=> ({
id : article.id,
fileName : article.fileName,
title : article.title,
content : content
}))
)
)
)
)
);
注意:这尚未经过语法检查或验证。请提供一个小的工作 StackBlitz 示例以获得更具体和语法检查的答案。
此代码首先获取所有文章。然后它使用 mergeMap 来处理文章并自动订阅内部的 Observables。forkJoin 允许我们使用articles.map 处理文章数组中的每篇文章。
然后我们对文章内容发出 http 请求,并将检索到的数据映射到所需的接口中。
结果是包含内容的 Observable<INewsArticles[]>。然后,您可以在模板中进行简单的插值绑定。
更新:您可以使用对象解构稍微缩短语法:
this.http.get<INewsArticles[]>(this._srcArticles).pipe(
mergeMap(articles=>
forkJoin(
articles.map(article=>
this.http.get('./assets/news-articles/content/'+article.fileName, {responseType : 'text'}).pipe(
map(content=> ({
...article,
content : content
}))
)
)
)
)
);
该...article
语法复制所有文章属性。然后你只需要添加content
.
推荐阅读
- html - 响应能力 - Chrome 中的 iPad 与 Mozilla Firefox 中的 iPad
- r - zoo() 如何填充 n 行,而原始 Dataframe 有 n-1 行?
- python - Django rest api DRF - ViewSet 从 get 中隐藏一个字段,但包含 put
- python - 排序时如何处理NULL值?
- php - PHP Laravel 发送邮件返回验证错误和空字段
- serial-port - 串口通讯打印问题
- sun-codemodel - 如何将枚举值作为参数传递给代码模型中的调用?
- amazon-iam - AWS IAM CDK:为用户标记和创建访问密钥
- php - 如何在不刷新页面的情况下在同一个 { div } 上显示表单成功消息?
- javascript - Electron 构建时自动启动 NodeJS