<!DOCTYPE html>
<html>

  <head>
    <script data-require="angularjs@1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="MyApp">
    
    <section ng-controller="MainCtl">
    
      <h1>Seleccione</h1>
      
      <selectable-list
        items="items"
        ng-model="selected"
      ></selectable-list>
      
      <h2>Seleccionados</h2>
      <ul>
        <li ng-hide="selected.length">Nadie</li>
        <li ng-repeat="i in selected">{{i.name}}</li>
      </ul>

    </section>
    
  </body>

</html>

angular.module("MyApp", [])
  .controller("MainCtl", ["$scope", ($scope) => {

    var roberto = {
      id: 4,
      name: "Roberto"
    };

    $scope.items = [{
        id: 1,
        name: "Juan"
      }, {
        id: 2,
        name: "Pedro"
      }, {
        id: 3,
        name: "Luis"
      },
      roberto, {
        id: 5,
        name: "Pablo"
      }, {
        id: 6,
        name: "Homero"
      },
    ];

    $scope.selected = [roberto];

  }])
  .directive("selectableList", () => {

    const template = `
            <ul>
                <li
                    ng-repeat="item in items track by item.id"
                >
                    <input
                        type="checkbox"
                        ng-model="item.$selected"
                        ng-change="updateSelected()"
                    >
                    <span ng-bind="item.name"></span>
                </li>
            </ul>`;

    return {
      strict: "EA",
      replace: true,
      template: template,
      require: '?ngModel',
      scope: {
        items: "=",
      },
      link(scope, el, attrs, ngModel) {
        // scope.items es definida por el usuario y
        // ngModel es una instancia de ngModelController o null
        var unregisterInit, selectedItems = [];

        // Cada vez que se seleccione o des-seleccione un
        // elemento, actualizamos el modelo
        scope.updateSelected = function(noDirty = false) {

          // Filtramos solo los items seleccionados
          selectedItems = scope.items.filter(i => i.$selected);

          if (ngModel) {
            ngModel.$setViewValue(selectedItems)

            // Si no se nos indica lo contrario, marcamos el 
            // modelo como $dirty y $touched, esto es para 
            // implemnetar con formularios
            if (!noDirty) {
              ngModel.$setDirty();
              ngModel.$setTouched();
            }

          }
        };

        const init = function(value) {
          // Nos des-suscribimos del primer $watch
          unregisterInit();

          // Si tenemos ngModel, le definimos el valor de los elementos
          // Seleccionados
          if (ngModel) {
            selectedItems = value.map((i) => {
              i.$selected = true;
              return i;
            });
            ngModel.$setViewValue(selectedItems);
          }

          // En caso de que se actualice "items", actualizamos el modelo
          scope.$watchCollection("items", () => {
            scope.updateSelected(true);
          });

          // Nullify
          value = null;

        };

        // Nos subscribimos al primer cambio del scope
        unregisterInit = scope.$watch(() => {
          var value;

          // Si tenemos ngModel, tomamos su valor
          if (ngModel) {
            value = ngModel.$modelValue;
          }

          // Si no lo definimos antes, o es null, lo definimos
          // como un array vacío
          if (!value) {
            value = [];
          }

          // Se lo mandamos a init()
          return value;

        }, init);
      }
    };

  });
# Creando una directiva en Angular que soporte ```ng-model```

Esto es simple, pero buscando en internet me di cuenta que la documentación que hay es mala, y en español sobretodo, inexistente.

Lo que vamos a hacer es crear una directiva de angular que soporte manejar un modelo con ```ng-model```, lo que me sorprende de esto es que buscando el primer resultado es una pregunta en StackOverflow llamada; [Create a directive that uses ng-model](https://stackoverflow.com/questions/14115701/angularjs-create-a-directive-that-uses-ng-model) donde la respuesta ganadora tiene 172 votos, pero personalmente diserto de esta respuesta, ya que no considero que conteste a la pregunta.

¿Por qué no usar esa respuesta? Porque queremos tener las ventajas de usar ```ng-models```, como el poder validarlo dentro de un formulario.

En mi caso en particular, tuve que hacer un listado dentro de un formulario, en el que cada item puede ser seleccionado y esto afecta a los que se va a enviar al final. No voy a entrar en detalle de como funciona esto, así que solo me centraré en mostrar como definir el modelo.

Para leer mas detalles, ingresa al post original:
http://log.exodica.com.ar/3C