Append html to an element in directive and make a local function to interact with it

100,390

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

Share:
100,390

Related videos on Youtube

harkor
Author by

harkor

Updated on July 21, 2022

Comments

  • harkor
    harkor almost 2 years

    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.

    • Davin Tryon
      Davin Tryon over 10 years
      Why not use template?
    • harkor
      harkor over 10 years
      For example, I have this style of input <input type="text" placeholder="{{lang('placeholderWhere')}}" name="where" id="where-input" ng-model="data.form.where.txt" google-places my-position erase-btn /> and I have this style of input <input type="text" id="what-input" placeholder="{{lang('placeholderWho')}}" name="who" ng-model="data.form.who.txt" typeahead="item for item in autoComplete.list['who'] | filter:$viewValue" autocomplete-api erase-btn /> How can I keep other directives ok with a template ?
    • harkor
      harkor over 10 years
      Sorry for crappy style => pastebin.com/9LeSatGH
    • Sakeer
      Sakeer almost 10 years
      good question. did you got the solution for this?
    • harkor
      harkor almost 10 years
      No sorry, I searched a lot of time and I found anything.
  • harkor
    harkor over 10 years
    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...
  • Vadim
    Vadim over 10 years
    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.
  • irth
    irth almost 10 years
    What about select options? how to append this within the select element tags.
  • Jakob Jenkov
    Jakob Jenkov over 9 years
    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().
  • ESP32
    ESP32 over 7 years
    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.
  • Vadim
    Vadim over 7 years
    @Gerfried Sure, in the 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