nj51
nj51

Reputation: 15

Dynamically added directive but content not showing

I am new to angular and am trying to create a voting poll app. Right now I have 4 input boxes. 1 question and 3 answers to use when creating a new poll. I also have a button that adds a new input box if you want to add another answer. I read if I want to dynamically at content to the DOM I should use a directive. I created one that adds the new html content I want that should also add a ng-model attribute so I can access the content that is in an array along with the other content. The input boxes that were originally there work fine but when I add a new one it won't access it.

Directive/function code:

votingApp.directive('addAnswers', [function(){

return {
    template:"<li><input type='text' ng-model='choices[3]'  /></li>",
    restrict: 'E'
}
}]);

Function that would add the new directive into the list of input boxes.

$scope.addAnswer = function(){

    var node = document.createElement("LI");



    var textnode = document.createElement("add-answers");
    node.appendChild(textnode);

    $scope.pollAnswers.appendChild(node);



};

Lastly where the it should be added to in the HTML.

      <form ng-submit="createPoll()">
        <p>Question</p>
        <input type="text" ng-model="pollQuestion" />

        <p>Answers</p>
      <ul id="answers">
        <li><input type="text" placeholder=" " ng-model="choices[0]" /></li>
        <li><input type="text" placeholder=" "  ng-model="choices[1]" /></li>
        <li><input type="text" placeholder=" "  ng-model="choices[2]" />    </li>
      </ul>
      <input id="create" type="submit" value="Create Poll" />
    </form>

Basically as I add a new input I am going to make the ng-model = to the length of the array. However, when I do this the array doesn't get a slot bigger when adding a new element.

Upvotes: 0

Views: 57

Answers (2)

csschapker
csschapker

Reputation: 129

Here's a plunk with a better example: http://plnkr.co/edit/gSWHCxgagMrF4OoEZDh1?p=preview

You could just ng-repeat based on your choices.

// controller
votingApp.controller('Controller', ['$scope', function($scope) {
    $scope.choices = [];

    $scope.addAnswer = function() {
        $scope.choices.push('');
    };
}]);

// html
<ul id="answers">
    <li ng-repeat="answer in choices track by $index">
        <input type="text" ng-model="choices[$index]" />
    </li>
</ul>

Here's some stuff from my plunk so it's easier to see:

votingApp.directive('answers', function() {
    return {
      restrict: 'E',
      scope: {
          choices: '='
      },
      template: '<li ng-repeat="answer in choices track by $index"><input type="text" ng-model="choices[$index]" /></li>'
    };
});

votingApp.controller('VotingController', [ 
  '$scope',
  function($scope) {
    $scope.choices = [];

    // if you want to start with some choices use this
    // $scope.choices = new Array(3);

    $scope.addAnswer = function() {
      $scope.choices.push('');
    };
  }
]);

<body ng-app="votingApp" ng-controller="VotingController">
    <ul>
      <answers choices="choices"></answers>
    </ul>
    <button ng-click="addAnswer()">Add Answer</button>
</body>

Upvotes: 1

illeb
illeb

Reputation: 2947

That's because your HTML code you are injecting here

var textnode = document.createElement("add-answers");

isn't compiled by angular (and so your directive is not resolved).

My suggestion is to use a ng-repeat instead, so your content will be compiled (and your directive will be constructed properly, in a more angularjs way), like this:

<add-answers ng-repeat="answer in answers"> </add-answers>

By doing this, you need to have an array answers in your scope, that you can accomplish this way in your addAnswer function:

$scope.answers = [];
$scope.addAnswer = function(){    
   var node = document.createElement("LI");

   $scope.answers.push({}); //new Answers
};

.

If you still need to use javascript to inject your components (sic!, don't do that!) then you will need to use the $compile service.

Upvotes: 2

Related Questions