<!DOCTYPE html>
<html ng-app="emailAddressesExample">

<head>
  <meta charset="utf-8" />
  <title>AngularJS test</title>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js" data-semver="1.2.16" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
  <script data-require="lodash.js@*" data-semver="2.4.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <div>
    <label>Email addresses</label>
    <email-address-list data-ng-model="emailAddresses" required></email-address-list>
  </div>
  <p>The email address list contents: {{emailAddresses}}</p>
</body>

</html>
(function(angular, _) {

  angular.module('emailAddressesExample', [])
    .controller('MainCtrl', function($scope) {
      $scope.emailAddresses = [];
    })

  .directive('emailAddressList', function() {
    return {
      templateUrl: 'emailaddresslist.html',
      restrict: 'E',
      require: 'ngModel',
      scope: {}, // This signifies an isolate scope
      link: function(scope, element, attributes, ngModelCtrl) {

        ngModelCtrl.$render = function() {
          if (ngModelCtrl.$viewValue.length === 0) {
            // If an array is provided without items, a single item is
            // added by default
            scope.emailAddresses = [undefined];
          } else {
            scope.emailAddresses = ngModelCtrl.$viewValue;
          }
        };

        scope.$watch('emailAddresses', function() {
          ngModelCtrl.$setViewValue(scope.emailAddresses);
        }, true);

        ngModelCtrl.$formatters.push(function(modelValue) {
          return _.compact(modelValue);
        });

        ngModelCtrl.$parsers.push(function(viewValue) {
          var compactedValue = _.compact(viewValue);
          // If 'required' is passed in via the element, at least one
          // valid email address must be entered for the element to be valid
          if (attributes.required) {
            if (compactedValue.length) {
              ngModelCtrl.$setValidity('emailAddresses', true);
            } else {
              ngModelCtrl.$setValidity('emailAddresses', false);
            }
          }
          return compactedValue;
        });
      },
      controller: function($scope) {

        $scope.add = function() {
          $scope.emailAddresses.push(undefined);
        };

        $scope.remove = function(index) {
          $scope.emailAddresses.splice(index, 1);
        };
      }
    };
  });

})(angular, _);
/* Styles go here */

<div>
    <input data-ng-model="emailAddresses[0]" type="email">
</div>
<div data-ng-repeat="emailAddress in emailAddresses track by $index" data-ng-if="!$first">
    <input data-ng-model="emailAddresses[$index]" type="email">
    <span>
        <button type="button" data-ng-click="remove($index)">x</button>
    </span>
</div>

<p><button type="button" data-ng-click="add()">Add another email address</button></p>