Quel est le moyen le plus simple de combiner ng-changé et ng-blur?
J'ai trouvé ce post: Comment laisser ng-model ne pas mettre à jour immédiatement?
Cependant, cela ne fonctionne plus dans angluar 1.2+. Existe-t-il un moyen d'obtenir le même comportement?
Je suppose que je dois stocker moi-même une copie de l'ancienne valeur et comparer la nouvelle valeur à celle sur flou si j'essaie de faire de même, ou existe-t-il un moyen plus simple?
Cela fait ce que je veux. Il stocke la valeur sur le focus et la compare à la nouvelle valeur de flou; s'il est modifié, il déclenche l'expression dans l'attribut.
app.directive('changeOnBlur', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, Elm, attrs, ngModelCtrl) {
if (attrs.type === 'radio' || attrs.type === 'checkbox')
return;
var expressionToCall = attrs.changeOnBlur;
var oldValue = null;
Elm.bind('focus',function() {
scope.$apply(function() {
oldValue = Elm.val();
console.log(oldValue);
});
})
Elm.bind('blur', function() {
scope.$apply(function() {
var newValue = Elm.val();
console.log(newValue);
if (newValue !== oldValue){
scope.$eval(expressionToCall);
}
//alert('changed ' + oldValue);
});
});
}
};
});
usage:
<input ng-model="foo" change-on-blur="someFunc()" />
Utilisez ng-model options
. De cette manière, ng-change
ne se déclenche que lorsque l'entrée est floue.
<input type="text"
ng-model="a.b"
ng-model-options="{updateOn: 'blur'}"
ng-change="onchange()"/>
Que diriez-vous de cette solution. Travaille pour moi:
<input ng-init="oldValue = value" ng-model="value"
ng-blur="oldValue != value && callYourFunc(foo)">
que diriez-vous ce plunkr ?
en utilisant le ng-blur
construit par angular, mettez à jour votre "valeur persistante" sur le flou
<input type="text" ng-model="boxValue" ng-blur="doneEditing(boxValue)">
lors de la sauvegarde, vérifiez que la valeur est différente
$scope.doneEditing = function(v) {
if (v !== $scope.persistedValue) // only save when value is different
$scope.persistedValue=v;
}
À ma connaissance, il n'y a pas d'option spéciale sur ng-blur
pour la pré-vérification de l'égalité. Un simple if
semble faire l'affaire
J'utilise AngularJs 1.2.x et je suis tombé sur le problème du changement, qui consiste à tirer sur chaque changement. ng-blur peut être utilisé mais il se déclenche même s'il n'y a pas de changement dans la valeur. Donc, les deux ne peuvent pas être utilisés efficacement.
Avec Angularjs 1.3.x, les choses sont plus simples avec ng-model-options
comme ci-dessous
invoquer la fonction de changement "onBlur"
ng-change="ctrl.onchange()" ng-model-options="{updateOn: 'blur'}"
Et
retarder l'invocation de la fonction de changement de 500 ms
ng-change="ctrl.onchange()" ng-model-options='{ debounce: 500 }'"
Revenons maintenant à la question d'obtenir de telles choses avec AngularJs 1.2.x
invoquer la fonction de changement "onBlur"
html
<input type="text" ng-model="ctrl.a.c" sd-change-on-blur="ctrl.onchange()" />
Or
<input type="text" ng-model="ctrl.a.c" sd-change-on-blur="ctrl.onchange(ctrl.a.c)" />
JS
app.directive('sdChangeOnBlur', function() {
return {
restrict: 'A',
scope: {
sdChangeOnBlur: '&'
},
link: function(scope, Elm, attrs) {
if (attrs.type === 'radio' || attrs.type === 'checkbox')
return;
var parameters = getParameters(attrs.sdChangeOnBlur);
var oldValue = null;
Elm.bind('focus', function() {
scope.$apply(function() {
oldValue = Elm.val();
});
})
Elm.bind('blur', function() {
scope.$apply(function() {
if (Elm.val() != oldValue) {
var params = {};
if (parameters && parameters.length > 0) {
for (var n = 0; n < parameters.length; n++) {
params[parameters[n]] = scope.$parent.$eval(parameters[n]);
}
} else {
params = null;
}
if (params == null) {
scope.sdChangeOnBlur();
} else {
scope.sdChangeOnBlur(params)
}
}
});
});
}
};
});
function getParameters(functionStr) {
var paramStr = functionStr.slice(functionStr.indexOf('(') + 1, functionStr.indexOf(')'));
var params;
if (paramStr) {
params = paramStr.split(",");
}
var paramsT = [];
for (var n = 0; params && n < params.length; n++) {
paramsT.Push(params[n].trim());
}
return paramsT;
}
retarder l'invocation de la fonction de changement de 500 ms
html
<input type="text" ng-model="name" sd-change="onChange(name)" sd-change-delay="300"/>
OR
<input type="text" ng-model="name" sd-change="onChange()" sd-change-delay="300"/>
JS
app.directive('sdChange', ['$timeout',
function($timeout) {
return {
restrict: 'A',
scope: {
sdChange: '&',
sdChangeDelay: '@' //optional
},
link: function(scope, Elm, attr) {
if (attr.type === 'radio' || attr.type === 'checkbox') {
return;
}
if (!scope.sdChangeDelay) {
scope.sdChangeDelay = 500; //defauld delay
}
var parameters = getParameters(attr.sdChange);
var delayTimer;
Elm.bind('keydown keypress', function() {
if (delayTimer !== null) {
$timeout.cancel(delayTimer);
}
delayTimer = $timeout(function() {
var params = {};
if (parameters && parameters.length > 0) {
for (var n = 0; n < parameters.length; n++) {
params[parameters[n]] = scope.$parent.$eval(parameters[n]);
}
} else {
params = null;
}
if (params == null) {
scope.sdChange();
} else {
scope.sdChange(params)
}
delayTimer = null;
}, scope.sdChangeDelay);
scope.$on(
"$destroy",
function(event) {
$timeout.cancel(delayTimer);
console.log("Destroyed");
}
);
});
}
};
}
]);
function getParameters(functionStr) {
var paramStr = functionStr.slice(functionStr.indexOf('(') + 1, functionStr.indexOf(')'));
var params;
if (paramStr) {
params = paramStr.split(",");
}
var paramsT = [];
for (var n = 0; params && n < params.length; n++) {
paramsT.Push(params[n].trim());
}
return paramsT;
}
les plnkrs pour les deux approches sont
Les versions les plus récentes d’AngularJS (maintenant en version 1.3 bêta) le supportent de manière native. Voir ma réponse ici
La solution qui a fonctionné pour moi était la suivante:
<input id="fieldId" type="text"
ng-model="form.fields.thisField"
ng-model-options="{ updateOn: 'blur' }"
ng-change="form.save()" />
J'ai trouvé cette solution ici
Cette page indique qu'elle nécessite la version 1.3.0+ d’AngularJS. Je l'ai testé avec AngularJS version 1.5.11 et cela fonctionne dans cette version pour moi.