it-roy-ru.com

AngularJS - Размытие + Изменено?

Какой самый простой способ совместить нг-измененный и нг-размытие?

Я нашел этот пост: Как позволить ng-модели не обновляться сразу?

Тем не менее, это больше не работает в Angluar 1.2+ Есть ли способ добиться того же поведения?

Я полагаю, что мне нужно сохранить копию старого значения самостоятельно и сравнить новое значение с размытым, если я пытаюсь сделать то же самое, или есть какой-то более простой способ?

19
Roger Johansson

Это делает то, что я хочу ... Он сохраняет значение в фокусе и сравнивает его с новым значением в размытии, если изменено, запускает выражение в атрибуте.

 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);
                        });         
                    });
                }
            };
        });

использование:

 <input ng-model="foo" change-on-blur="someFunc()" />
14
Roger Johansson

Используйте ng-model options. Таким образом, ng-change будет срабатывать только тогда, когда вход размыт.

<input type="text" 
       ng-model="a.b" 
       ng-model-options="{updateOn: 'blur'}" 
       ng-change="onchange()"/>
43
Niels Steenbeek

Как насчет этого решения. Работает для меня:

<input ng-init="oldValue = value" ng-model="value"
       ng-blur="oldValue != value && callYourFunc(foo)">
4
Michael

как насчет этот plunkr ?

используя встроенный в ng-blur angular, обновите ваше «постоянное значение» при размытии

<input type="text" ng-model="boxValue" ng-blur="doneEditing(boxValue)">

при сохранении убедитесь, что значение отличается

$scope.doneEditing = function(v) {
  if (v !== $scope.persistedValue) // only save when value is different
    $scope.persistedValue=v;
}

На ng-blur нет специальной опции для предварительной проверки равенства, о которой я знаю. Простая if, кажется, добивается цели

3
Chris Montgomery

Я использую AngularJs 1.2.x и наткнулся на проблему запуска ng-change при каждом изменении. Можно использовать ng-blur, но оно срабатывает, даже если значение не меняется. Таким образом, оба не могут быть использованы эффективно.

С Angularjs 1.3.x проще использовать ng-model-options, как показано ниже

для вызова функции изменения "onBlur" 

ng-change="ctrl.onchange()" ng-model-options="{updateOn: 'blur'}"

А также 

задержать вызов функции изменения на 500 мс 

ng-change="ctrl.onchange()" ng-model-options='{ debounce: 500 }'"

Теперь вернемся к вопросу о получении таких вещей с AngularJs 1.2.x

для вызова функции изменения "onBlur"

html

<input type="text" ng-model="ctrl.a.c" sd-change-on-blur="ctrl.onchange()" /> или

<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;
}

задержать вызов функции изменения на 500 мс

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;
}

pLNKRS для обоих подходов 

http://plnkr.co/edit/r5t0KwMtNeOhgnaidKhS?p=preview

http://plnkr.co/edit/9PGbYGCDCtB52G8bJkjx?p=info

3
Yogesh Manware

Более новые версии AngularJS (сейчас в версии 1.3 beta) поддерживают это изначально. Смотрите мой ответ здесь

2
manikanta

Решение, которое работало для меня, было следующим:

<input id="fieldId" type="text"
ng-model="form.fields.thisField"
ng-model-options="{ updateOn: 'blur' }"
ng-change="form.save()" />

Я нашел это решение здесь

На этой странице сказано, что требуется AngularJS версии 1.3.0+. Я протестировал его с AngularJS версии 1.5.11, и он работает в этой версии для меня.

1
Kmeixner