Angular 4, How to update [(ngModel)] with a delay of 1 seconds

前端 未结 6 1545
攒了一身酷
攒了一身酷 2021-02-05 16:17

Since ngModel is updating instantly how to put a delay.

  

        
相关标签:
6条回答
  • 2021-02-05 16:23
    update_fields(){
    
      this.service.yourTask(){
        .subscribe(data => {
          setTimeout(()=>{ //your task }, 4000)
        }    
      }
    }
    
    
    someFunction() {
        setTimeout(() => /* code to execute */, 3000)
    }
    
    0 讨论(0)
  • 2021-02-05 16:24

    Answer by Fredrik Lundin updated for Angular 6:

    Template:

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

    Component:

    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;
        }
      }
    }
    
    0 讨论(0)
  • 2021-02-05 16:27

    Lots of solutions using setTimeout(), but this will cause the function to be called each time the model changes, a simple way to prevent this is to clear the timeout first

    e.g.

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

    this will only call the function once after the last update is made and the timeOutDuration has elapsed

    0 讨论(0)
  • 2021-02-05 16:30

    Rxjs and Observables are the perfect candidate for this type of task! Here is an example of how it can be achieved:

    Template:

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

    Component:

    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 is a type of object that acts both as an observable and observer - meaning you can both subscribe to it and emit values from it (with next())!

    debounceTime waits for the provided time in ms until it allows for new changes

    distinctUntilChanges will not allow the same input to pass through two times in a row

    switchMap takes the latest observable from the chain so you don't get multiple results at once

    0 讨论(0)
  • 2021-02-05 16:38

    Add delay inside your update_fields() method.

    Like:

    public update_fields(data)
      setTimeout(function() {
       //call service
      }, 1000);
    
    0 讨论(0)
  • 2021-02-05 16:45

    Here's a solution that works with a callback.

    view template:

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

    component class:

        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(){...}
    
    0 讨论(0)
提交回复
热议问题