Dans AngularJS, je peux anti-rebondir un modèle en utilisant les options ng-model.
ng-model-options="{ debounce: 1000 }"
Comment puis-je supprimer un modèle dans Angular? J'ai essayé de rechercher anti-rebond dans la documentation mais je n'ai rien trouvé.
https://angular.io/search/#stq=debounce&stp=1
Une solution serait d'écrire ma propre fonction anti-rebond, par exemple:
import {Component, Template, bootstrap} from 'angular2/angular2';
// Annotation section
@Component({
selector: 'my-app'
})
@Template({
url: 'app.html'
})
// Component controller
class MyAppComponent {
constructor() {
this.firstName = 'Name';
}
changed($event, el){
console.log("changes", this.name, el.value);
this.name = el.value;
}
firstNameChanged($event, first){
if (this.timeoutId) window.clearTimeout(this.timeoutID);
this.timeoutID = window.setTimeout(() => {
this.firstName = first.value;
}, 250)
}
}
bootstrap(MyAppComponent);
Et mon html
<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">
Mais je recherche une fonction intégrée, y en a-t-il une dans Angular?
javascript
angular
koningdavid
la source
la source
Réponses:
Mis à jour pour RC.5
Avec Angular 2, nous pouvons anti-rebond en utilisant l'opérateur RxJS
debounceTime()
sur l'valueChanges
observable d' un contrôle de formulaire :Plunker
Le code ci-dessus comprend également un exemple de la façon de limiter les événements de redimensionnement de la fenêtre, comme demandé par @albanx dans un commentaire ci-dessous.
Bien que le code ci-dessus soit probablement la manière angulaire de le faire, il n'est pas efficace. Chaque frappe et chaque événement de redimensionnement, même s'ils sont déboncés et limités, entraînent l'exécution de la détection des modifications. En d'autres termes, le rebond et la limitation n'affectent pas la fréquence d'exécution de la détection des modifications . (J'ai trouvé un commentaire GitHub de Tobias Bosch qui le confirme.) Vous pouvez le voir lorsque vous exécutez le plunker et vous voyez combien de fois
ngDoCheck()
est appelé lorsque vous tapez dans la zone de saisie ou redimensionnez la fenêtre. (Utilisez le bouton bleu "x" pour exécuter le plunker dans une fenêtre séparée pour voir les événements de redimensionnement.)Une technique plus efficace consiste à créer vous-même des observables RxJS à partir des événements, en dehors de la "zone" d'Angular. De cette façon, la détection des modifications n'est pas appelée à chaque fois qu'un événement se déclenche. Ensuite, dans vos méthodes de rappel d'abonnement, déclenchez manuellement la détection de changement - c'est-à-dire que vous contrôlez le moment où la détection de changement est appelée:
Plunker
J'utilise
ngAfterViewInit()
au lieu dengOnInit()
pour m'assurer queinputElRef
c'est défini.detectChanges()
exécutera la détection des modifications sur ce composant et ses enfants. Si vous préférez exécuter la détection des modifications à partir du composant racine (c'est-à-dire exécuter une vérification complète de la détection des modifications), utilisez à laApplicationRef.tick()
place. (J'ai mis un appel àApplicationRef.tick()
dans les commentaires dans le plunker.) Notez que l'appeltick()
provoquerangDoCheck()
un appel.la source
.fromEvent()
abonnementsSi vous ne voulez pas vous en occuper
@angular/forms
, vous pouvez simplement utiliser un RxJSSubject
avec des liaisons de modification.view.component.html
view.component.ts
Cela déclenche la détection des changements. Pour un moyen qui ne déclenche pas la détection des modifications, consultez la réponse de Mark.
Mettre à jour
.pipe(debounceTime(300), distinctUntilChanged())
est nécessaire pour rxjs 6.Exemple:
la source
.pipe(debounceTime(300), distinctUntilChanged())
est nécessaire pour rxjs 6keyUp
événementinput.nativeElement
dans unmat-table
, qui a cessé de fonctionner lorsque le nombre de colonnes a été modifiéElle pourrait être mise en œuvre sous forme de directive
utilisez-le comme
échantillon de composant
la source
import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';
toimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';
etthis.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()
tothis.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
Comme le sujet est ancien, la plupart des réponses ne fonctionnent pas sur Angular 6/7/8/9 et / ou utilisent d'autres bibliothèques.
Voici donc une solution courte et simple pour Angular 6+ avec RxJS.
Importez d'abord les éléments nécessaires:
Initialiser sur
ngOnInit
:Utilisez de cette façon:
PS: Pour des solutions plus complexes et efficaces, vous voudrez peut-être toujours vérifier d'autres réponses.
la source
Pas directement accessible comme dans angular1 mais vous pouvez facilement jouer avec les observables NgFormControl et RxJS:
Ce billet de blog l'explique clairement: http://blog.oughttram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
Ici, c'est pour une saisie semi-automatique mais cela fonctionne dans tous les scénarios.
la source
[...]
est une liaison cible unidirectionnelle. Pourquoi le conteneur peut-il être notifiévalueChanges
? ça ne devrait pas être qch. comme(ngFormControl)="..."
?Vous pouvez créer un RxJS (v.6) Observable qui fait ce que vous voulez.
view.component.html
view.component.ts
la source
rsjs/Rx
, j'ai eu des erreurs lors de l'utilisation de l'importation comme vous l'avez écrite ... donc dans mon cas, c'est maintenant:import { Observable } from 'rxjs/Rx';
import { Observable } from 'rxjs';
.pipe
appelpipe(debounceTime(300), distinctUntilChanged())
Pour quiconque utilise lodash, il est extrêmement facile de supprimer n'importe quelle fonction:
puis lancez simplement quelque chose comme ça dans votre modèle:
la source
Solution avec abonné d'initialisation directement en fonction événement:
Et html:
la source
J'ai résolu ce problème en écrivant un décorateur anti-rebond. Le problème décrit peut être résolu en appliquant le @debounceAccessor à l'accesseur set de la propriété.
J'ai également fourni un décorateur anti-rebond supplémentaire pour les méthodes, qui peut être utile pour d'autres occasions.
Cela rend très facile la suppression du rebond d'une propriété ou d'une méthode. Le paramètre est le nombre de millisecondes que le anti-rebond doit durer, 100 ms dans l'exemple ci-dessous.
Et voici le code pour les décorateurs:
J'ai ajouté un paramètre supplémentaire pour le décorateur de méthode qui vous permet de déclencher la méthode APRÈS le délai anti-rebond. Je l'ai fait pour pouvoir par exemple l'utiliser lorsqu'il est associé à des événements de survol de la souris ou de redimensionnement, où je voulais que la capture se produise à la fin du flux d'événements. Dans ce cas cependant, la méthode ne retournera pas de valeur.
la source
Nous pouvons créer une directive [debounce] qui écrase la fonction viewToModelUpdate par défaut de ngModel par une fonction vide.
Code de directive
Comment l'utiliser
la source
Fichier HTML:
Fichier TS:
la source
Une solution simple serait de créer une directive que vous pouvez appliquer à n'importe quel contrôle.
l'utilisation serait
la source
Angular 7
.J'ai passé des heures là-dessus, j'espère pouvoir faire gagner du temps à quelqu'un d'autre. Pour moi, l'approche suivante d'utilisation
debounce
sur un contrôle est plus intuitive et plus facile à comprendre pour moi. Il est basé sur la solution docs angular.io pour la saisie semi-automatique, mais avec la possibilité pour moi d'intercepter les appels sans avoir à dépendre de la liaison des données au DOM.Plunker
Un scénario d'utilisation pour cela pourrait être de vérifier un nom d'utilisateur après sa saisie pour voir si quelqu'un l'a déjà pris, puis d'avertir l'utilisateur.
Remarque: n'oubliez pas, cela
(blur)="function(something.value)
peut avoir plus de sens pour vous en fonction de vos besoins.la source
DebounceTime dans Angular 7 avec RxJS v6
Lien source
Lien de démonstration
Dans un modèle HTML
Dans le composant
la source
Vous pouvez également résoudre ce problème en utilisant un décorateur, pour une instance en utilisant le décorateur anti- rebond de utils-decorator lib (
npm install utils-decorators
):la source
C'est la meilleure solution que j'ai trouvée jusqu'à présent. Met à jour le
ngModel
surblur
etdebounce
emprunté à https://stackoverflow.com/a/47823960/3955513
Puis en HTML:
Sur
blur
le modèle est explicitement mis à jour en utilisant du javascript brut.Exemple ici: https://stackblitz.com/edit/ng2-debounce-working
la source