我想按国家搜索城市。
我有两个不同的共享组件: 第一个用于国家搜索,这将发出选定的国家ID 然后第二个共享组件获取此国家/地区ID并传递给服务 但它不会过滤城市并返回数据库中的所有城市 当我调试休息服务时: 如果我不通过countryId它是工作并返回所有城市, 但我通过countryId;不久之后countryId值改变(null或0) 并返回整个城市。 这个场景有什么问题。 感谢。
//Component
export class CitySharedComponent implements OnInit {
cities = new Array<City>();
searchTerm$ = new Subject<string>();
public selectedCountryId = new BehaviorSubject(0);
@Input() countryId: any;
constructor(private service: CityService) { }
ngOnInit() {
this.service.search(this.searchTerm$, this.selectedCountryId.getValue(), 1)
.subscribe(results => {
this.cities = results;
});
}
onKeyup(searchText: string) {
if (searchText != null)
this.searchTerm$.next(searchText);
}
ngOnChanges(changes: { [propName: string]: SimpleChange }) {
if (changes['countryId']) {
if (changes['countryId'].currentValue == null || changes['countryId'].currentValue == undefined)
changes['countryId'].currentValue = 0;
this.cities = null;
this.selectedCountryId.next(changes['countryId'].currentValue);
}
}
}
//Service
search(terms: Observable<string>, countryId, lang): Observable<City[]> {
var headers = new Headers();
headers.append('Authorization', `bearer ${this.auth_key}`);
headers.append('Content-Type', 'application/json');
return terms
.distinctUntilChanged()
.switchMap(term => this.http.get(`${this.url}/search/${countryId}/${lang}/${term}`, { headers })
.map(data => data.json())
)
}
答案 0 :(得分:1)
无法在代码中找到ngOnDestroy。你需要在destroy中取消订阅你的Observable。
答案 1 :(得分:0)
嗯,即时错误是您没有订阅国家/地区ID主题,这就是为什么当您从中发出新值时没有变化的原因 - 只是没有人在听。您刚刚在ngOnInit()
中选择了第一个值并将其传递给search()
。它永远不会改变。
除此之外,不要更改changes
集合中的任何内容。更改不属于您的数据通常是个坏主意,因此将其视为只读集合。它可以更简单:this.selectedCountryId.next(changes['countryId'].currentValue || 0);
。
<强>更新强>
可以做得更简单。您根本不需要了解任何可观察的服务。让它只是获取原始值。处理可观察物是另一个问题。
//Component
export class CitySharedComponent implements OnInit {
cities = new Array<City>();
searchTerm$ = new Subject<string>();
public selectedCountryId = new BehaviorSubject(0);
// if you don't need to store this value for your component then
// you can safely remove getter and this field.
// just leave setter, it will be enough.
private _countryId: any;
@Input()
get countryId: any {
return this._countryId;
}
set countryId(value: any) {
this._countryId = value;
this.selectedCountryId.next(this._countryId || 0);
}
constructor(private service: CityService) { }
ngOnInit() {
this.searchTerm$.distinctUntilChanged().combileLatest(
this.selectedCountryId.distinctUntilChanged(), (_term, _countryId) => {
return {
term: _term,
countryId: _countryId
}
}
)
.switchMap(t => this.service.search(t.term, t.countryId, 1))
.subscribe(results => {
this.cities = results;
}); // and of course do not forget to unsubscribe from this
}
onKeyup(searchText: string) {
if (searchText != null)
this.searchTerm$.next(searchText);
}
}
//Service
search(term: string, countryId, lang): Observable<City[]> {
var headers = new Headers();
headers.append('Authorization', `bearer ${this.auth_key}`);
headers.append('Content-Type', 'application/json');
return this.http.get(`${this.url}/search/${countryId}/${lang}/${term}`, { headers })
.map(data => data.json());
}