Angularjs input[placeholder] directive breaking with ng-model

16,212

Solution 1

Just few modifications in your sample:

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

You can test it here: http://plnkr.co/edit/8m54JO?p=preview

Not sure, that it is the best solution, anyway it works. Even if you type the same text, that you have in your placehold attribute, cause it checks the model's value on focus.

Solution 2

You can also checkout an Angular.JS module that implements the "placeholder" attribute for older web browsers:

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

Share:
16,212
dane
Author by

dane

Updated on July 19, 2022

Comments

  • dane
    dane almost 2 years

    So first day on the job with angularjs and i'm not quite getting it. I'm trying to mimic an html5 placeholder using an angular directive. It totally works until I add an ng-model to the field and then it only works after a user interacts with the field and also breaks any value the field had.

    code up here http://jsbin.com/esujax/32/edit


    the directive

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

    the html

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

    seems super simple but i'm lost

  • dane
    dane over 11 years
    do i have to have a controller and add the value to scope to do this. the way i thought of it a directive should be reusable on any element?
  • Pythonic
    Pythonic over 11 years
    You are right, my fault. Fixed it to work without initial value: plnkr.co/edit/8m54JO?p=preview
  • Blowsie
    Blowsie over 10 years
    this will cause memory leasks, dont forget to unbind the events!