Demo of dynamic numeric select component in Angular

by Julien Roy

HTML

<script src="https://code.angularjs.org/1.5.5/angular.min.js"></script>
<div ng-app="demo" ng-controller="demoCtrl as ctrl">
  <p>
    Cinq :
    <num-select nb-options="5" ng-model="ctrl.firstSelect"></num-select>
    <input type="button" ng-click="ctrl.firstSelect = 3" value="Set to 3">
    <br /> Valeur sélectionnée : {{ctrl.firstSelect}}
  </p>
  <p>
    Dix :
    <num-select nb-options="10" start-at-one="true" ng-model="ctrl.secondSelect"></num-select>
    <br /> Valeur sélectionnée : {{ctrl.secondSelect}}
  </p>
  <p>
    Neuf :
    <num-select nb-options="9" ng-model="ctrl.thirdSelect"></num-select>
    <br /> Valeur sélectionnée : {{ctrl.thirdSelect}}
  </p>
  <hr>
  <h2>Component</h2>
  <p>
    Neuf :
    <num-select-comp nb-options="9" ng-model="ctrl.thirdSelect"></num-select-comp>
    <br /> Valeur sélectionnée : {{ctrl.thirdSelect}}
  </p>

</div>

CSS

p {
  border-bottom-width: 1px;
  border-color: #CCC;
}

JavaScript

'use strict';
angular.module('demo', [])
  .controller('demoCtrl', function() {
    this.firstSelect = 5;
    this.secondSelect = 10;
    this.thirdSelect = undefined;
  })
  .component('numSelectComp', {
    bindings: {
      nbOptions: '<',
      ngModel: '=',
      onChange: '&'
    },
    require: 'ngModel',
    controller: function() {
      this.$onInit = function() {
        this.num = this.updateOptions();
      };
      this.$onChanges = function() {
        //only one way bindings
        this.num = this.updateOptions();
      };
      this.updateOptions = function() {
        var i = 0,
          res = [];
        if (angular.isDefined(this.startAtOne) &&
          this.startAtOne === 'true') {
          i = 1;
        }
        res = [];
        for (; i <= this.nbOptions; i += 1) {
          res.push(i);
        }
        return res;
      };
    },
    template: '<select ng-model="$ctrl.ngModel" ng-options="n for n in $ctrl.num"></select>'
  })
  .directive('numSelect', function() {
    return {
      restrict: 'E',
      scope: {
        nbOptions: '=',
        ngModel: '=',
        onChange: '&'
      },
      require: 'ngModel',
      link: function(scope, element, attrs, ngModel) {

        scope.num = [];

        var updateOptions = function() {
          var i = 0;
          if (angular.isDefined(attrs.startAtOne) &&
            attrs.startAtOne === 'true') {
            i = 1;
          }
          scope.num = [];
          for (; i <= scope.nbOptions; i += 1) {
            scope.num.push(i);
          }
        };

        //watch to nbOptions Change
        scope.$watch('nbOptions', function() {
          updateOptions();
        }, true);

        element.bind('change', function() {
          scope.$apply(function() {
            scope.onChange();
          });
        });
      },
      template: '<select ng-model="ngModel" ng-options="n for n in num"></select>'
    };
  });