22

In my AngularJS application, I have different complex inputs everywhere. For example, some inputs have a directive to use autocompletion with Google Places or with autocompletion from Twitter Bootstrap.

I'm searching for a way to make a directive which displays an erase button when we add some text like iOS feature.

I made this one, but the scope.erase doesn't start, nor does the ng-show.

Is it possible to add HTML after the text input and "play" with them inside the controller?

My test:

app.directive('eraseBtn', function($parse, $compile){

return {
    require: 'ngModel',
    restrict: "A",
    transclude: true,
    link : function(scope, element, attrs, model){

        element.parent().append('<button ng-click="erase()" ng-show="model.length > 0" class="erase-btn">x</button>');

        scope.erase = function(){
            console.log('Erase test');
        }
    }
}
});

I don't want to use a template because all of my inputs' HTML are really different.

alex
  • 6,818
  • 9
  • 52
  • 103
harkor
  • 483
  • 1
  • 5
  • 14

1 Answers1

42

You can create custom inputs inside link function of your directive depending on values of the model. If you want that elements to be bind to model or use directives to build them, you should use $compile (and don't forget to call compiled template with model):

HTML

<!DOCTYPE html>
<html ng-app="demo">

  <head>
    <script data-require="angular.js@*" data-semver="1.2.10" src="http://code.angularjs.org/1.2.10/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="demoController">
    <div demo-directive ng-repeat="input in inputs"></div>
  </body>

</html>

JavaScript

angular.module('demo', []).
  controller('demoController', function($scope) {
    $scope.inputs = [{
      inputType: 'checkbox',
      checked: true,
      label: 'input 1'
    }, {
      inputType: 'text',
      value: 'some text 1',
      label: 'input 2'
    }];

    $scope.doSomething = function() {
      alert('button clicked');
    };
  }).
  directive('demoDirective', function($compile) {
    return {
      template: '<div><label>{{input.label}}: </label></div>',
      replace: true,
      link: function(scope, element) {
        var el = angular.element('<span/>');
        switch(scope.input.inputType) {
          case 'checkbox':
            el.append('<input type="checkbox" ng-model="input.checked"/><button ng-if="input.checked" ng-click="input.checked=false; doSomething()">X</button>');
            break;
          case 'text':
            el.append('<input type="text" ng-model="input.value"/><button ng-if="input.value" ng-click="input.value=\'\'; doSomething()">X</button>');
            break;
        }
        $compile(el)(scope);
        element.append(el);
      }
    }
  });

Plunker: http://plnkr.co/edit/pzFjgtf9Q4kTI7XGAUCF?p=preview

Vadim
  • 8,701
  • 4
  • 43
  • 50
  • I don't understand... Your example give me a method with different type attribute... My problem is I call different other directives... I Just want to add a button after the input and can make a controller click inside this directive... – harkor Jan 30 '14 at 10:40
  • I have updated the example, but general idea is the same: write directive that displays custom input + close button (on demand). Inputs (checkbox, text) may be any custom input with other directives and not only standard html inputs. – Vadim Jan 30 '14 at 12:08
  • What about select options? how to append this within the select element tags. – irth Jun 26 '14 at 09:35
  • 1
    In my experience, element.append() does not work inside of a directive. AngularJS's append() version strips out all HTML. This only works if you also include jQuery in your page, in which case AngularJS uses jQuery's append(). – Jakob Jenkov Aug 22 '14 at 08:19
  • Can I link the "input" variable to the link function without knowing its name? The directive is not well re-usable if I need to name my variables in the html the same way as in the directive. – ESP32 Sep 20 '16 at 19:15
  • 1
    @Gerfried Sure, in the http://plnkr.co/edit/1WEY8laNKbwpM6swBYcw?p=preview you can see an example in which `input` is a value taken from isolated scope of directive, which is bound to attribute `demo-directive` of the element – Vadim Sep 20 '16 at 19:28