Angular 4, Как обновить [(ngModel)] с задержкой в ​​1 секунду

Поскольку ngModel обновляется мгновенно, как поставить задержку.

  <input type="text" value="{{item.task_name}}" name="task_name" [(ngModel)]="item.task_name" (ngModelChange)="update_fields([item.task_name])" >

Мне нужно сохранить task_name с задержкой в ​​одну секунду, вызвав update_fields (), чтобы избежать мгновенных обращений к сервису.

Спасибо


person Community    schedule 27.06.2017    source источник
comment
вместо этого добавьте задержку к вашему сервису   -  person mumair    schedule 27.06.2017


Ответы (6)


Rxjs и Observables - идеальный кандидат для этого типа задач! Вот пример того, как этого можно достичь:

Шаблон:

<input type="text" [value]="item.task_name"(keyup)="term$.next($event.target.value)">

Компонент:

import ......

import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';

@Component{(
  ...
)}
export class YourComponent {

  term$ = new Subject<string>();

  constructor() {
    this.term$
      .debounceTime(1000)
      .distinctUntilChanged()
      .switchMap(term => /*do something*/);
  }
}

subject - это тип объекта, который действует как наблюдаемый и как наблюдатель - это означает, что вы можете как подписаться на него, так и испускать из него значения (с next())!

debounceTime ожидает в течение указанного времени в мс, пока не разрешит новые изменения

distinctUntilChanges не позволит один и тот же ввод пройти два раза подряд

switchMap берет последнюю наблюдаемую из цепочки, поэтому вы не можете получить сразу несколько результатов

person Fredrik Lundin    schedule 27.06.2017
comment
Извините, я новичок, не могли бы вы также обновить часть импорта, Becoz Cannot find name subject error, даже я добавил - import {Observable} from rxjs / Observable; также - person ; 27.06.2017
comment
@JomyJoseph добавил к моему ответу импорт :) - person Fredrik Lundin; 27.06.2017
comment
Я просто использовал subscribe вместо switchMap, и это сработало. - person Gowtham Gopalakrishnan; 17.07.2017
comment
Не уверен, как я его использую, но я обнаружил, что функция switchMap (Angular5) требует возврата. Так что верните Observable.empty () - или что угодно, например. - person PeterS; 22.01.2018

Ответ Фредрика Лундина, обновленного для Angular 6:

Шаблон:

<input type="text" [value]="item.task_name" (keyup)="term$.next($event.target.value)">

Компонент:

import ......

import { Subject, EMPTY } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';

@Component{(
  ...
)}
export class YourComponent implements OnDestroy {

  term$ = new Subject<string>();

  private searchSubscription: Subscription;

  constructor() {
    this.searchSubscription = this.term$.pipe(
      debounceTime(1000),
      distinctUntilChanged(),
      switchMap(term => {
        /*do something*/
        return EMPTY;
      })
    ).subscribe();
  }

  ngOnDestroy() {
    //remember to unsubscribe on destroy

    if (this.searchSubscription) {
      this.searchSubscription.unsubscribe();
      this.searchSubscription = null;
    }
  }
}
person vangras    schedule 11.04.2019
comment
это отличный пример, который я использую, но в канале нет. перед функциями, они должны быть разделены запятыми. - person Ryan; 09.06.2019
comment
Это должен быть принятый ответ. Работает как шарм. - person Peter; 28.07.2019
comment
@vangras, может, вы объясните, чем ваше решение отличается или лучше от решения Фредрика? - person El Mac; 16.10.2020

Множество решений с использованием setTimeout(), но это приведет к тому, что функция будет вызываться каждый раз при изменении модели, простой способ предотвратить это - сначала очистить тайм-аут.

e.g.

timeOut;
timeOutDuration = 1000;

update_fields(data) {
  clearTimeout(this.timeOut);
  this.timeOut = setTimeout(() => {
     //do something
  }, this.timeOutDuration);
}

это вызовет функцию только один раз после того, как будет выполнено последнее обновление и истечет timeOutDuration

person Tiaan Le Grange    schedule 26.08.2020

Добавьте задержку в свой update_fields() метод.

Нравится:

public update_fields(data)
  setTimeout(function() {
   //call service
  }, 1000);
person anoop    schedule 27.06.2017
comment
какая разница между нашими ответами? - person Rahul Singh; 27.06.2017
comment
никогда не замечал вашего ответа перед отправкой., был в режиме редактора., в любом случае я мог найти разницу, это таймер :), (4000 мс, 3000 мс)., это должно быть 1000, вы можете исправить. :) - person anoop; 27.06.2017

Вот решение, которое работает с обратным вызовом.

просмотреть шаблон:

<input ... #element (ngModelChange)="delayAction(element, doSomething, [$event])">

класс компонента:

    actionsByElements = new Map<HTMLElement, Subscription>();

    delayAction(element: HTMLElement, cb: Function, args: any[]) {
      // cancel countdown by element
      let action = this.actionsByElements.get(element);
      if(action) {
        action.unsubscribe();
      }

      // start new countdown by element
      action = timer(1000).subscribe(() => cb.apply(this, args));
      this.actionsByElements.set(element, action);
    }

    doSomething(){...}
person Martin Cremer    schedule 21.10.2018

person    schedule
comment
Если я наберу xyz через 1 секунду. не будет ли он звонить трижды с задержкой 1 сек? - person ; 27.06.2017
comment
Да, ты можешь попробовать - person Rahul Singh; 27.06.2017