Входной сигнал углового входа [placeholder] с использованием ng-модели

Итак, первый день на работе с angularjs, и я не совсем понял. Я пытаюсь подражать html5 placeholder, используя директиву angular. Он полностью работает до тех пор, пока я не добавлю 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>

кажется супер простым, но я потерян

Ответ 1

Всего несколько изменений в вашем примере:

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

Не уверен, что это лучшее решение, так или иначе оно работает. Даже если вы набираете тот же текст, который у вас есть в атрибуте placehold, вызывают его проверку значения модели в фокусе.

Ответ 2

Вы также можете проверить модуль Angular.JS, который реализует атрибут "placeholder" для более старых веб-браузеров:

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

Ответ 3

Я создал директиву-заполнителем, которая может принимать выражения углов, а также скрывает текст-заполнитель на входе. Вы можете прочитать про местозаполнитель в 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/info/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);

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