Angularjs输入[占位符]指令与ng模型冲突

Angularjs input[placeholder] directive breaking with ng-model

本文关键字:ng 模型 冲突 指令 输入 占位符 Angularjs      更新时间:2023-09-26

所以第一天用angularjs工作,我不太明白。我试图用angular指令模拟html5占位符。它完全有效,直到我将ng模型添加到字段中,然后只有在用户与字段交互并破坏字段的任何值之后它才有效。

代码在这里http://jsbin.com/esujax/32/edit


指令

App.directive('placehold', function(){
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var insert = function() {
        element.val(attrs.placehold);
      };
      element.bind('blur', function(){
        if(element.val() === '')
          insert();
      });
      element.bind('focus', function(){
        if(element.val() === attrs.placehold)
          element.val('');
      });
      if(element.val() === '')
        insert();
    }
  }
});

html

<textarea ng-model="comment" placehold="with a model it doesn't work"></textarea>

看起来超级简单,但我迷失了

您的示例中只有一些修改:

app.directive('placehold', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attr, ctrl) {      
      var value;
      var placehold = function () {
          element.val(attr.placehold)
      };
      var unplacehold = function () {
          element.val('');
      };
      scope.$watch(attr.ngModel, function (val) {
        value = val || '';
      });
      element.bind('focus', function () {
         if(value == '') unplacehold();
      });
      element.bind('blur', function () {
         if (element.val() == '') placehold();
      });
      ctrl.$formatters.unshift(function (val) {
        if (!val) {
          placehold();
          value = '';
          return attr.placehold;
        }
        return val;
      });
    }
  };
});

您可以在此处进行测试:http://plnkr.co/edit/8m54JO?p=preview

不确定,这是最好的解决方案,无论如何它是有效的。即使您键入了与占位符属性中相同的文本,因为它会在焦点上检查模型的值。

您还可以签出Angular。JS模块,实现旧浏览器的"占位符"属性:

https://github.com/urish/angular-placeholder-shim

我创建了一个占位符指令,它可以接受angularjs表达式,还可以在输入时隐藏占位符文本。您可以在上阅读有关占位符的信息http://blog.f1circle.com/2013/09/supporting-placeholders-in-non-html5.html

要点如下。

(function(angular, app) {
  "use strict";
  app.directive('placeholder',["$document", "$timeout", function($document, $timeout){
    var link = function(scope,element,attrs,ctrl){
      // if you dont use modernizr library use the solution given at
      // http://stackoverflow.com/questions/5536236/javascript-check-for-native-placeholder-support-in-ie8
      // to check if placeholder is supported natively
      if(Modernizr.input.placeholder){
        return;
      }
      /*
        The following keys all cause the caret to jump to the end of the input value
        27,  Escape
        33,  Page up
        34,  Page down
        35,  End
        36,  Home
        Arrow keys allow you to move the caret manually, which should be prevented when the placeholder is visible
        37,  Left
        38,  Up
        39,  Right
        40,  Down
        The following keys allow you to modify the placeholder text by removing characters, which should be prevented when the placeholder is visible
        8,  Backspace
        46  Delete
      */
      var pTxt, modelValue, placeholding = false, badKeys = [27,33,34,35,36,37,38,39,40,8,46];
      var unplacehold = function(){
        if(!placeholding){
          return;
        }
        placeholding = false;
        element.removeClass('placeholder');
        element.val('');
      };
      var placehold = function(){
        if(placeholding || modelValue){
          return;
        }
        placeholding = true;
        element.addClass('placeholder');
        element.val(pTxt);
      };
      var moveCaret = function(elem, index) {
        var range;
        if (elem.createTextRange) {
          range = elem.createTextRange();
          range.move("character", index);
          range.select();
        } else if (elem.selectionStart) {
          elem.focus();
          elem.setSelectionRange(index, index);
        }
      };
      attrs.$observe('placeholder',function(value){
        pTxt = value;
        placeholding = false;
        placehold();
      });
      ctrl.$parsers.unshift(function (value){
        modelValue = value;
        if(!value){
          placehold();
        }
        if(placeholding){
          return '';
        }
        return value;
      });
      ctrl.$formatters.unshift(function (value){
        if(!value){
          placehold();
          modelValue = '';
          return pTxt;
        }
        return value;
      });
      element.on('click focus contextmenu',function(event){
        if($document[0].activeElement  !== this){
          return;
        }
        if(!modelValue){
          moveCaret(this,0);
        }
      });
      element.on('blur',function(){
        placehold();
      });
      element.on('keydown',function(e){
        if(!placeholding){
          return;
        }
        if(_.contains(badKeys,e.keyCode)){
          if(e.preventDefault){
            e.preventDefault();
          }
          return false;
        }
        unplacehold();
      });
      element.on('keyup',function(e){
        if(modelValue){
          return;
        }
        placehold();
        moveCaret(this,0);
      });
      element.on('paste',function(e){
        $timeout(function(){
          modelValue = element.val();
        },0);
      });
    };
    return{
      restrict: 'A',
      require: 'ngModel',
      link : link,
      priority:3,
    };
  }]);
})(angular, app);

这适用于除复制和粘贴相同占位符文本之外的所有情况。