2016-03-04 123 views
2

我有一个小问题(或大问题)与观察值相结合。我正在实施某种标签输入。RxJS结合观察值

this._allTags是所有可用的标签。

我有4个流:

this._suggestions = new this.rx.Subject; 
    this._searchText = new this.rx.Subject; 
    this._selectedIndex = new this.rx.Subject; 
    this._eventsStream = new this.rx.Subject; 

检索方法:

search(searchText) { 
    this._searchText.onNext(searchText); 
    this._selectedIndex.onNext(-1); 
} 

的KeyDown方法:

keyDown(event) { 
    this._eventsStream.onNext(event); 
} 

搜索逻辑:

const partitionSearchText = this._searchText 
    .partition((searchText) => !!searchText); //check if searchText is not empty 

    //put filtered array to this._suggestions stream 
    partitionSearchText[0] 
    .subscribe((searchText) => this._suggestions.onNext(
     this._allTags.filter((item) => ~item.name.toLowerCase().indexOf(searchText.toLowerCase())) 
    )); 

    //put empty array to this._suggestions stream if there is no searchText 
    partitionSearchText[1] 
    .subscribe((searchText) => this._suggestions.onNext([])); 

我想实施活动。如果有searchText和keyDown事件,那么我想增加this._selectedIndex,但是如果this._selectedIndex的长度与this._suggestions相同,那么不要增加它。

这是迄今为止我所实现的:

const eventsWithSearchText = this._searchText 
    .map((searchText) => !!searchText ? this._eventsStream : this.rx.Observable.empty()) 
    .switch() 

    const keyDownEvents = eventsWithSearchText 
    .filter((event) => event.keyCode === DOWN_KEY) 

    keyDownEvents 
    .subscribe((event) => event.preventDefault()) 

    const isNotLast = this._selectedIndex 
    .combineLatest(this._suggestions, (index, sugg) => index !== sugg.length - 1); 

    keyDownEvents 
    .subscribe((item) => { 
     this._selectedIndexValue++ 
     this._selectedIndex.onNext(this._selectedIndexValue); 
    }); 

所以,它增加this._selectedIndex,但是当它同this._suggestions长度不停止。

你能帮忙吗?

https://plnkr.co/edit/eh21d0d8U0VIsUyCjlkJ?p=preview

+1

请准备小提琴。 – halfzebra

+0

它是:https://plnkr.co/edit/eh21d0d8U0VIsUyCjlkJ?p=preview – dakolech

回答

3

我做到了!下面是代码:

const eventsWithSearchText = this._searchText 
    .map((searchText) => !!searchText ? this._eventsStream : this.rx.Observable.empty()) 
    .switch() 

    const keyDownEvents = eventsWithSearchText 
    .filter((event) => event.keyCode === DOWN_KEY) 

    keyDownEvents 
    .subscribe((event) => event.preventDefault()) 

    const keyUpEvents = eventsWithSearchText 
    .filter((event) => event.keyCode === UP_KEY) 

    keyUpEvents 
    .subscribe((event) => event.preventDefault()) 

    const enterEvents = eventsWithSearchText 
    .filter((event) => event.keyCode === ENTER_KEY) 

    enterEvents 
    .subscribe((event) => event.preventDefault()) 

    const isNotLast = this._selectedIndex 
    .combineLatest(this._suggestions, (index, sugg) => index !== sugg.length - 1); 

    const keyDownAndNotLast = keyDownEvents 
    .map(() => +1) 
    .withLatestFrom(isNotLast, (value, notLast) => notLast ? value : false) 
    .filter((item) => item) 

    const keyUpEventsAndNotFirst = keyUpEvents 
    .map(() => -1) 
    .withLatestFrom(this._selectedIndex, (value, index) => !!index ? value : false) 
    .filter((item) => item) 

    this.rx.Observable.merge(
    keyDownAndNotLast, 
    keyUpEventsAndNotFirst, 
    enterEvents 
     .map(() => ({reset: true})) 
    ) 
    .scan((acc, value) => value.reset ? -1 : acc + value, -1) 
    .subscribe((item) => { 
     this._selectedIndex.onNext(item); 
    }); 

https://plnkr.co/edit/soaChC?p=preview

希望这会帮助别人。