Search code examples
javascriptpythonhtmlangularjsdynamicform

AngularJS Dynamic Template with indexed scope variable arrays


I'm using AngularJS and trying to create a form where I can dynamically add new inputs, similar to this fiddle: http://jsfiddle.net/V4BqE/ (Main HTML below, working code in fiddle).

<div ng-app="myApp" ng-controller="MyCtrl">
  <div add-input>
    <button>add input</button>
  </div>
</div>

I would like to be able to use a HTML template for my form since the input I'm adding is ~300 lines long. My issue is I cannot figure out how to index the scope variable containing the data when used in a template. I've tried to make my own modified version of the above code on plnkr http://plnkr.co/edit/4zeaFoDeX0sGTuBMCQP2?p=info . However, when I click the button no form elements appear.

Online (plnkr) I get a 404 not found for my template.html, but I think that is just a plnkr limitation. On my machine with a Python HttpServer I get an Error: [$parse:syntax] for the $templateRequest and a TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. when using the $http.get method.

Any advice for getting the indexed scope variable array to work with an external html file?

Thanks, JR

Edit: Update plnkr link


Solution

  • You can do it without directive & external template

    what you are trying to do does not require a directive (it actually much simple with the basic angularjs tools)

    http://plnkr.co/edit/LVzGN8D2WSL2nR1W7vJB?p=preview

    html

    <body>
    
      <div class="container" ng-app="myApp" ng-controller="MyCtrl">
    
        <button class="btn btn-primary" type="button" ng-click="addPhoneInput()">add input</button>
    
        <form>
          <div ng-repeat="item in telephoneNumbers">
            <hr>
            <input type="text" ng-model="item.phone">
          </div>
        </form>
        
        
        <hr>
        
        <div class="well">
          <h4>Phone Numbers,</h4>
          <p ng-repeat="item in telephoneNumbers">{{item.phone}}</p>
        </div>
      </div>
    </body>
    

    js

    var app = angular.module('myApp', []);
    
    app.controller('MyCtrl', ['$scope', function($scope) {
      // Define $scope.telephone as an array
      $scope.telephoneNumbers = [];
    
      $scope.addPhoneInput = function() {
        $scope.telephoneNumbers.push({});
      };
    
      // This is just so you can see the array values changing and working! Check your console as you're typing in the inputs :)
      $scope.$watch('telephoneNumbers', function(value) {
        console.log(value);
      }, true);
    }]);
    

    If you insist using a directive,

    http://plnkr.co/edit/BGLqqTez2k9lUO0HZ5g1?p=preview

    phone-number.template.html

    <div>
      <hr>
      <input type="text" ng-model="ngModel" >
    </div>
    

    html

    <body>
    
      <div class="container" ng-app="myApp" ng-controller="MyCtrl">
    
        <button class="btn btn-primary" type="button" ng-click="addPhoneInput()">add input</button>
    
        <form>
          <phone-number ng-repeat="item in telephoneNumbers" ng-model="item.phone"></phone-number>
        </form>
        
        
        <hr>
        
        <div class="well">
          <h4>Phone Numbers,</h4>
          <p ng-repeat="item in telephoneNumbers">{{item.phone}}</p>
        </div>
      </div>
    </body>
    

    js

    var app = angular.module('myApp', []);
    
    app.controller('MyCtrl', ['$scope', function($scope) {
      // Define $scope.telephone as an array
      $scope.telephoneNumbers = [];
    
      $scope.addPhoneInput = function() {
        $scope.telephoneNumbers.push({});
      };
    
      // This is just so you can see the array values changing and working! Check your console as you're typing in the inputs :)
      $scope.$watch('telephoneNumbers', function(value) {
        console.log(value);
      }, true);
    }]);
    
    app.directive('phoneNumber', function(){
      return {
        replace:true,
         scope: {
          ngModel: '=',
        },
        templateUrl: "phone-number.template.html"
      }
    });