Search code examples
javascriptangularjsangularjs-directiveangularjs-controller

Add new HTML content with different values in Angularjs


I created a directive to add some content whenever the button "add" is clicked. But I don't know how to get all values in these new inputs.

HTML Code

angular.module('myApp', [])
  .controller('myController', function() {

  })
  .directive('addContent', function($document, $compile) {
    return {
      restrict: 'A',
      replace: false,
      link: function(scope, element, attr) {
        element.on('click', function() {
          var newcontent = '<input type="text" ng-model="myModel"><br>';
          angular.element($document[0].querySelector('.newcontent')).append($compile(newcontent)(scope));
        })
      }
    }

  })
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="newcontent" ng-app="myApp" ng-controller="myController">
  <button type="button" add-content>Add</button><br><br>
</div>

So, how can I set a different ng-model value to each one new input that is created and, how can I get this values in my controller?


Solution

  • You could go with something like this:

    The Idea:

    • A base name can be defined from the html where the directive is being applied.
    • An incremental number is used in the directive when creating new inputs (the view controller (programmer) where this model is used must be aware of that). Actually, you could use any other strategy you'd prefer better in this case. I've used this one for simplicity and stating my point.

    The code (see below snippet):

    In the directive

    • Create a counter for incrementing as new inputs are added: var count = 0;
    • Take the base name specified in the html with var model = scope.$eval(attr['addContent']);
    • Modify the newcontent variable to use that base name and the incremental counter like this: var newcontent = '<input type="text" ng-model="' + model + (count++) + '"><br>';

    The controller

    • For organization, create a variable for holding the base name: $scope.buttonModel = 'buttonModelReference';
    • Access the value of those new models like this: $scope[$scope.buttonModel + $scope.index] where $scope.index is the index of the input (where 0 is the first input created)

    The view

    • Use the modified directive like this add-content="buttonModel" where buttonModel is the variable defined in the controller.

    Plus code (for demonstration purposes only)

    • The showModel function shows the value of one (dynamic created) input passing as reference the index of the input (0 zero is the index of the first input created)

    The Snippet

    angular.module('myApp', [])
      .controller('myController', function($scope) {
    
        $scope.index;
        $scope.buttonModel = 'buttonModelReference';
    
        $scope.showModel = function() {
          console.log($scope[$scope.buttonModel + $scope.index]);
        }
    
      })
      .directive('addContent', function($document, $compile) {
        var count = 0;
        return {
          restrict: 'A',
          replace: false,
          link: function(scope, element, attr) {
            element.on('click', function() {
              var model = scope.$eval(attr['addContent']);
              var newcontent = '<input type="text" ng-model="' + model + (count++) + '"><br>';
              angular.element($document[0].querySelector('.newcontent')).append($compile(newcontent)(scope));
            })
          }
        }
    
      })
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div class="newcontent" ng-app="myApp" ng-controller="myController">
      <button type="button" ng-click="showModel()">showModel</button> &nbsp; <input ng-model="index" type="number" placeholder="select the model index starting from 0" /> <br><br>
      <button type="button" add-content="buttonModel">Add</button><br><br>
    </div>