Javascript-форум (https://javascript.ru/forum/)
-   Angular.js (https://javascript.ru/forum/angular/)
-   -   Angular 2. Фильтрация с RxJs (https://javascript.ru/forum/angular/66681-angular-2-filtraciya-s-rxjs.html)

Digan 01.01.2017 23:20

Angular 2. Фильтрация с RxJs
 
Хочу реализовать простейший фильтр списка. За основу взял один из туториалов из документации. Но мне нужно немного изменить поведение: если в туториале с пустым текстовым полем список получается пустой, то мне нужно, чтобы в этом в списке после загрузки страницы выводились все элементы массива.

Вот темплейт:
<div>
    <input #searchBox id="search-box" type="text" (keyup)="search(searchBox.value)"/>
    <ul>
        <li *ngFor="let contact of displayedContacts | async" class="contact">
            <span>{{contact.name}}</span>
        </li>
    </ul>
</div>


Часть кода компонента:
contacts: Array<any>;
displayedContacts: Observable<any[]>;
private searchTerms = new Subject<string>();
...
this.displayedContacts = this.searchTerms
      .debounceTime(300)
      .distinctUntilChanged()
      .switchMap(term => this.filterContacts(term))
      .catch(error => {
        console.log(error);
        return Observable.of<any[]>([]);
      });
...
search(term: string): void {
    this.searchTerms.next(term);
  }


То что мне нужно пока получается добиться с помощью такого кода:
setTimeout(()=>{
        this.searchTerms.next("");
      }, 1500);


Но должен быть нормальный способ это сделать.

destus 02.01.2017 07:44

Digan,
Метод filterContacts еще покажи. В ngOnInit компонента не получится вынести прокидывание нужного тебе значения?
this.searchTerms.next("");

Или делай через BehaviorSubject с установкой нужного тебе значения при создании.

Digan 02.01.2017 10:49

Цитата:

Сообщение от destus (Сообщение 439522)
Или делай через BehaviorSubject с установкой нужного тебе значения при создании.

Спасибо. Это действительно помогло.
private searchTerms = new BehaviorSubject<string>("");

Получается Subject получается нельзя также инициализировать.

Общий вопрос по rxJs. За счет чего при использовании этой библиотеки не блокируется страница при перестройки dom?
У меня в списке 3 тыс. элементов. Если rxJs не использовать, то при фильтрации происходит кратковременное но подвисание при перестройке dom.

destus 02.01.2017 18:16

Digan,
Цитата:

Получается Subject получается нельзя также инициализировать
BehaviorSubject хранит последнее значение и передает его подписавшемуся обсерверу.
Цитата:

У меня в списке 3 тыс. элементов. Если rxJs не использовать, то при фильтрации происходит кратковременное но подвисание при перестройке dom.
А как фильтруешь? При каждом нажатии клавиши? Все такие такие вещи как debounceTime используются не просто так, а чтобы пользователь сначала написал что ищет, а затем будет обращение к апи, фильтрации какой-то коллекции и т.д. Если посмотреть в исходный код, то никакой магии там нет. Есть какая-то предикатная функция, которая выполняется для каждого элемента в потоке https://github.com/ReactiveX/rxjs/bl...ator/filter.ts.

Ну и не забываем использовать trackBy вместе с директивой ngFor.

Digan 03.01.2017 13:25

Цитата:

Сообщение от destus (Сообщение 439550)
Digan,
А как фильтруешь? При каждом нажатии клавиши?

На событие keyUp. Я так понимаю сделать задержку перед фильтрацией коллекции нельзя без rxjs.

destus 03.01.2017 14:29

Цитата:

Сообщение от Digan (Сообщение 439584)
На событие keyUp. Я так понимаю сделать задержку перед фильтрацией коллекции нельзя без rxjs.

Можно, вот пример на ваниле из underscore

_.debounce = function(func, wait, immediate) {
    var timeout, result;

    var later = function(context, args) {
      timeout = null;
      if (args) result = func.apply(context, args);
    };

    var debounced = restArgs(function(args) {
      if (timeout) clearTimeout(timeout);
      if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(later, wait);
        if (callNow) result = func.apply(this, args);
      } else {
        timeout = _.delay(later, wait, this, args);
      }

      return result;
    });

    debounced.cancel = function() {
      clearTimeout(timeout);
      timeout = null;
    };

    return debounced;
  };

рони 03.01.2017 14:47

destus,
зачем нужно в 10 строке проверка и в 24 строке обнуление?

destus 03.01.2017 16:52

рони,
Цитата:

зачем нужно в 10 строке проверка
Чтобы не запускалось несколько таймеров и отложенного вызова функции func несколько раз. То есть если говорить о keyup, обработчик запустится, если небыло повторного вызова этого типа события и прошло wait ms.

рони 03.01.2017 17:31

Цитата:

Сообщение от destus
Чтобы не запускалось несколько таймеров

зачем нужно проверять есть ли что-то в timeout? перед тем как остановить таймер, не проще просто остановить без проверок.
Цитата:

Сообщение от destus
if (timeout) clearTimeout(timeout);

и без
Цитата:

Сообщение от destus
timeout = null;


destus 03.01.2017 18:11

b]рони[/b],
Можно и так. Но в моем случае был копипаст с исходников библиотеки.


Часовой пояс GMT +3, время: 20:10.