我有两个组件,其中一个是主要组件html中的子路由。
每当我在主要组件中选择类别的复选框时,便会将它们分配给服务中的变量(字符串数组)。在子路由中,我订阅了一个可观察到的服务变量。我的目标是更新子路线的视图以仅显示那些类别的书。
因此,当服务变量的值更改时,我不应该看到日志吗(因为我在子组件中给出了console.log())? 值每次更改都不会订阅获取更新的值吗? 最后,订阅是否调用ngOnChanges()方法? (以更新视图)
我的代码:- 父Component.html:-
selectedCategories: string[] = [];
//...
categoryFilterSelect(){
this.userService._filterByGenre = this.selectedCategories;
}
父Component.ts:-
export class HomeComponent implements OnInit {
allBooks: Book[] = [];
selectedCategories: string[];
filteredBooks: Book[];
constructor(private userService: UserService) {}
ngOnInit() {
//initially display all books
this.userService.getAllBooks().subscribe(data => {
this.allBooks = data;
this.filteredBooks = this.allBooks;
});
//This part not working
this.userService.filterByGenre.subscribe(data => {
this.selectedCategories = data;
//this line not working
console.log(this.selectedCategories);
//perform filter logic here and update the filteredBooks array based
// onselected categories
}
);
}
}
第二个组件的ts :-(路由到Parent Component.html中)
<div class="container">
<div class="child" *ngFor="let book of filteredBooks">
....
</div>
</div>
second component.html
export class UserService {
_filterByGenre: string[] = [];
public get filterByGenre(): Observable<string[]> {
return of(this._filterByGenre);
}
}
service.ts
x2
控制台输出:- [] (因为最初没有选择类别,所以将其记录下来。)
我的Git回购:- https://github.com/Lucifer-77/ATL
答案 0 :(得分:1)
@Lucifer,事情并没有您所想的那样。角不是神奇的。不用担心,这是一开始的常见错误。当您订阅一个Observable时,Angular不会放一个“老大哥”来查看数据发生了什么。例如当我们对调用dbs的httpClient.get(url)进行预订时,对dbs Angular的任何更改都不会考虑到这一点。 (它不能做到)。
因此,您需要创建一个服务,说Angular考虑了更改:您需要使用类似的Subject。让我来展示一项有效的服务
private _filterByGenre:string[];
private filterByGenreSource = new Subject<any>();
filterByGenreObservable=this.filterByGenreSource.asObservable();
get filterByGenre()
{
return this._filterByGenre
}
set filterByGenre(value) //when we use dataService.filterBtGenre=...
{
this._filterByGenre=value; //equal to the private variable
this.filterByGenreSource.next(value) //say to Angular that something change
}
您可以订阅filterByGenreObservable
this.dataService.filterByGenreObservable.subscribe(data => {
this.selectedCategories = [...data]; //(*)
});
//(*) is we make simply this.selectedCategories=data, we can not see the data change
//so, I used the spread operator
如果我们做类似的事情
this.dataService.filterByGenre = this.selectedCategories;
在使用setter时,发出一个新值
好吧,我不使用p-checkbox,但是您可以在此stackblitz
中使用此答案的代码更新好,很显然,我们希望在更改类别时做出一些“改变”。
想象一下,我们有一个名为allBooks的数组,我们希望按选定的类别进行过滤。但是首先我们要更改发送给用户服务的数据,使其与p-checkbox更加相似,因此我将函数categoryFileterSelect更改为以数组形式发送,而不是[true,false,false,true] else [“ Horror” ,“科幻小说”]
categoryFilterSelect() {
this.dataService.filterByGenre =
this.options.filter((x, index) => this.selectedCategories[index]);
}
所以,我们可以写
this.userService.filterByGenreObservable.subscribe(
data => {
this.filteredBooks=this.allBooks.filter(x=>data.indexOf(x.genre)>=0)
},
error => null,
() => console.log("error")
);
好吧,我首先希望使用this.userService.filterByGenre的值进行一次调用,因此我将使用rxjs运算符startWith这样,最后我的订阅变为
this.userService.filterByGenreObservable.pipe(
startWith(this.userService.filterByGenre))
.subscribe(
data => {
this.filteredBooks=data?this.allBooks.filter(x=>data.indexOf(x.genre)>=0)
:this.allBooks
},
error => null,
() => console.log("error")
);
答案 1 :(得分:0)
请尝试在第二个组件中对filterByGenre()进行以下调用。
this.userService.filterByGenre().subscribe((data:string[]) => {
this.selectedCategories = data;
console.log(this.selectedCategories);
//perform filter logic here and update the filteredBooks array based
// onselected categories
}