2017-09-22 15 views
0

국가별로 도시를 검색하고 싶습니다.각도 4 관측 가능한 여러 번 전화 서비스

나는이 두 개의 서로 다른 공유 구성 요소 : 국가 검색을위한 첫 번째 일이 방출 선택한 국가 ID를 다음 두 번째 구성 요소는이 나라 ID를 얻을 에 서비스를 전달하지만이 도시를 필터링하고 데이터베이스에있는 모든 도시를 반환하지 않습니다 공유 .
내가 쉬는 상태에서 디버그 할 때 : countryId를 전달하지 않으면 모든 도시를 반환하고 모든 도시를 반환하지만 countryId를 전달합니다. 잠시 후 countryId 값이 변경되면 (null 또는 0) 전체 도시가 반환됩니다. 이 scenerio에는 어떤 문제가 있습니다. 감사합니다. .

//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

글쎄, 즉각적인 오류가 당신이 국가 ID 주제에 가입하지 않았다, 당신은 그것에서 새로운 가치를 방출 할 때 변경 사항이 없습니다 그 이유는 - 단지 아무도 듣고되지 않습니다. ngOnInit()에서 첫 번째 값을 선택하고 search()으로 전달했습니다. 그것은 결코 변하지 않을 것입니다.

그 외에도 changes 컬렉션의 내용을 변경하지 마십시오. 일반적으로 사용자가 아닌 데이터를 변경하는 것은 좋지 않으므로 읽기 전용 컬렉션으로 취급하십시오. 더 간단하게 할 수 있습니다 : this.selectedCountryId.next(changes['countryId'].currentValue || 0);.

UPDATE는

그것은 간단하게 수행 할 수 있습니다. 모든 관찰 대상에 대해 서비스를 알릴 필요는 없습니다. 원시 값을 가져 오도록합시다. 관측 대상을 다루는 것은 별개의 관심사입니다.

//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()); 
} 
+0

먼저 quickrespone에게 감사드립니다. 아래 코드를 변경했지만 작동하지 않습니다. DB에있는 모든 도시를 반환합니다. ngOnInit() { this.selectedCountryId.subscribe (data => { this.search (data); }); } 검색 (ID : 숫자) { this.service.search (this.searchTerm $으로, ID 1) .subscribe (결과 => { = this.cities의 결과, 입력 코드 'here' }) ; } 그러나 하드 코딩 된 값을 검색 (예 : countryId = 25)으로 보내면 예상대로 작동합니다. –

+0

@muratkurtun, 나는 나의 대답을 업데이트했다. 원래 전화에서 답변을하고 있었는데 코드를 편집하는 것이 매우 불편했습니다 :) –

+0

감사합니다. 예상대로 작동합니다. 나는 너의 대답을 받아 들였다. –

0

코드에서 ngOnDestroy를 찾을 수 없습니다. Observables의 파기를 해제해야합니다.

관련 문제