Brad W
Brad W

Reputation: 2558

How to get the ng-model of inputs appended to the form to have their own scope?

I have the below directive. The directive attribute goes on a counter button and adds a text input element to my form each time the incrementer button is clicked. Each added input takes text input independently until I add the ng-model to the directive's template. Then when I type in one input they all update together.

How can I get the directive to give each added input it's own scope while still using the same ng-model='equipment.equipment_name' for all of them?

Additionally the counter button to add inputs and the space for those respective inputs sits in an ng-repeat itself. So in the same form I display multiple types of equipment. A user may in turn have multiple instances of any one type of equipment. I need them to be able to assign a unique name to each instance of any type.

myApp.directive('addinputs', function ($compile) {
  return {
    restrict: 'A',
    scope: true,
    link: function (scope ,element) {

      //binds to a button intended to add text inputs to my form
      element.bind('click', function () {

        //refers to a div that has a binding to a counter value
        var resourceParents = document.getElementsByClassName('count');

        //initial number of inputs needed to get names for the resource category
        var resourceChildren = 0;

        //References multiple resource categories where inputs will be added
        var childId = 'space-for-inputs' + scope.$index;

        //Updates the count for the number of inputs needed
        for (var i = 0; i < resourceParents.length; i++) {
          resourceChildren += parseInt(resourceParents[i].innerHTML);
        };

        var inputTemplate = "<div class='\resource-name-input input_wrapper\'><input ng-model='\equipment.equipment_name\' type='\text\' name='\textInput\'></div>"

        //adds the new input above the previous
        angular.element(
            document.getElementById(childId))
            .append($compile(inputTemplate)(scope)
        );

        scope.$apply();
      });
    }
  };
});

Upvotes: 0

Views: 711

Answers (2)

Hieu TB
Hieu TB

Reputation: 162

You might want to use an array to store data of multiple input element. Please have look at my update here: http://jsfiddle.net/53m6max7/

I also use ng-repeat to add input elements instead of just append them. Because ng-repeat have multiple children scopes. It make sure equipment_name value will have difference value in difference input.

    scope.equipments = scope.equipments || []; //prepare the array
    scope.equipments.push({}); //add new item

    var resourceNameInput = document.getElementsByClassName('resource-name-input');

    if(resourceNameInput.length === 0) {
      //add an ng-repeat element, but only one time  
      var inputTemplate = "<div class=\'resource-name-input input_wrapper\' ng-repeat=\'equipment in equipments\'><input ng-model=\'equipment.equipment_name\' type=\'text\' name=\'textInput\'></div>";

      //adds the new input above the previous
      angular.element(
          document.getElementById(childId))
          .append($compile(inputTemplate)(scope)
      );
    }

Upvotes: 0

null
null

Reputation: 7926

You can create a new scope by calling scope.$new() and passing that into the $compile statement. But I don't think that will do what you want. Take a look into this plunker.

It creates a inputs array on the scope and adds an input object each time the button is pressed. The view does a ng-repeat over each input and renders out the input element with it's own scope. (The scope is automatically generated because I used ng-include in this example).

Upvotes: 0

Related Questions