Angularjs- adding/removing dynamic html elements (dropdown)

22,120

There is no need for $watch in your link function - you have already established two-way binding by specifying = on your scope property. And you can use a plain template, without having to compile.

templateUrl: 'template.html',

where template.html is:

<label class="item item-input">
  <div class="style-select">
    <select ng-model="demoDisplay.selection" ng-options="day for day in demoDays"></select>
    <br>
  </div>
</label>

Notice that the select is bound to demoDisplay.selection, which will be created on each field and be accessible on the parent scope via two-way binding. Also, note that within ng-options, I changed scope.demoDays to just demoDays. In a directive's template you only need to use the property's name to access a scope value.

You can use the directive inside ng-repeat to create additional fields when the button is clicked:

<div ng-repeat="field in data.fields">
  <div demo-display="field" demo-days="days"></div>
</div>

Here is a working plunker: http://plnkr.co/edit/pOY0l18W7wEbfSU7DKw2?p=preview

Share:
22,120
msreekm
Author by

msreekm

Updated on April 16, 2020

Comments

  • msreekm
    msreekm about 4 years

    here is my code- http://plnkr.co/edit/oTWXbLIKOxoGTd4U0goD?p=preview

    1. why is the days dropdown does not data bind with scope.demoDays, it is always empty?

    2. is this the correct way to add dropdown dynamically? If user adds 5 dropdown, how to get the results , will ng-model="selectedDay" create an array of selection? any suggestions?

    Thank you

    var app = angular.module('plunker', []);
    
    app.controller('MainCtrl', function($scope, $compile) {
    
      var counter = 0;
      $scope.fields = [];
    
      $scope.days =['Day','Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
    
        $scope.addField = function() {          
         $scope.fields.push({name:"test " + counter++});
        };
    });
    
    
    
    app.directive('demoDisplay', function($compile){
        return {
        scope:{
            demoDisplay:"=", //import referenced model to our directives scope
            demoDays:"="
          },
         link:function (scope, elem, attr, ctrl) 
          {
            scope.$watch('demoDisplay', function(){ // watch for when model changes
    
              elem.html("") //remove all elements
    
              angular.forEach(scope.demoDisplay, function(d){ //iterate list
                  var s = scope.$new(); //create a new scope
                  angular.extend(s,d); //copy data onto it
                  console.log(scope.demoDays);
    
                  var template = '<label class="item item-input"><div class="style-select"><select ng-model="selectedDay" ng-options="day for day in scope.demoDays"></select><br></div></label>';
                  elem.append($compile(template)(s)); // compile template & append
              });
            }, true) //look deep into object
          }
        }
    })
    

    html

    <button ng-click="addField()">Add Field</button>
    
    <div demo-display="fields" demo-days="days"></div>
    
    • Saghir A. Khatri
      Saghir A. Khatri about 10 years
      please post code here, instead of referring to other sites. Thx
    • msreekm
      msreekm about 10 years
      copied js and html here. It is much easier to see JS code running in plnkr.
  • Anthony Chu
    Anthony Chu about 10 years
    This change will make the dropdowns show up, but they are basically redrawn whenever the fields array changes and all selected values are lost.
  • markstewie
    markstewie about 10 years
    Yeah, there is definitely a better way of going about it. But this makes it work.
  • msreekm
    msreekm about 10 years
    Thanks for the explanation and simplifying the code !
  • msreekm
    msreekm about 10 years
    j.wittwer's answer keep's the selected values,thanks for the response.