Dynamically Add Elements to the Page With Angular's ng-repeat and ng-include

Dave Ceddia bio photo By Dave Ceddia Comment

There are some times when you might want to dynamically add elements to the page in response to some user action. Maybe you’re writing a form builder app, and users can add chunks of the form one at a time.

In this case, you want the order of the displayed forms to match the order of the button clicks. So if you have 3 buttons (A, B, C) and the user clicks (B, C, A), then you want form B to be added first, then C, then A.

Here’s an example that works this way. Try clicking the buttons.

The controller has an array of form template names. When a button is clicked, the matching form template name is added to an array of displayed forms. An ng-repeat directive loops array over the list of displayed forms, and uses ng-include to render the templates.

The HTML is simple, and for sake of making it easy to understand, it includes some inline templates. In a real app you’d probably want to put these in files and integrate them into your build process.

<body ng-app="exampleApp" ng-controller="DynamicFormCtrl as ctrl">
  <div>
    <button ng-click="ctrl.addForm(0)">Form One</button>
    <button ng-click="ctrl.addForm(1)">Form Two</button>
    <button ng-click="ctrl.addForm(2)">Form Three</button>
  </div>
  
  <div ng-repeat="form in ctrl.displayedForms track by $index">
    <ng-include src="form"></ng-include>
  </div>
  
  <script type="text/ng-template" id="form1.tpl.html">
    <label>
      Form one is an input: <input type="text" />
    </label>
  </script>

  <script type="text/ng-template" id="form2.tpl.html">
    <label>
      Form two gives you choices: <input type="radio"/> <input type="radio"/>
    </label>
  </script>
  
  <script type="text/ng-template" id="form3.tpl.html">
    <button>Form three is a button</button>
  </script>
</body>

The JS code is very simple. All it needs to do is add items to an array when the user clicks buttons.

angular.module("exampleApp", [])
  .controller("DynamicFormCtrl", function() {
    var ctrl = this;
    
    var forms = [
      "form1.tpl.html",
      "form2.tpl.html",
      "form3.tpl.html",
    ];
    
    ctrl.displayedForms = [];
    
    ctrl.addForm = function(formIndex) {
      ctrl.displayedForms.push(forms[formIndex]);
    }
  });

One important thing to notice with this approach is that you need to use the “track by” syntax (in this case, track by $index) if you want to allow repeat values - otherwise you’ll get an error saying “Duplicates in a repeater are not allowed.”

If you don’t want to allow repeats, just check before adding each form to the displayedForms array.

Choosing a framework is difficult.

Learning React? Sign up and get my React Learning Timeline PDF, and also weekly-ish articles about React, Angular, and JavaScript.

A few emails per month — unsubscribe any time.
comments powered by Disqus