Tabla de Contenidos

9.4 Ejemplo de directiva

En este tema retornamos el ejemplo del seguro médico para añadir una directiva. La directiva consiste en usar el widget de Datepicker de JQuery UI para que aparezca un calendario al pinchar sobre el campo “fechaCreacion” en la página detalle.html.

Para que funciona el Datepicker es necesario añadir lo siguiente a la página index.html:

    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/css/smoothness/jquery-ui-1.10.0.custom.min.css" />   
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>    
    <script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/jquery-ui.js"></script>

La directiva se llamara “caDatepciker” y se usará como un atributo HTML. El valor del atributo será el formato de fecha que queremos que tenga el Datepicker según los formatos de fecha definidos por $.datepicker.formatDate.

Por lo tanto la directiva se usará de la siguiente manera:

<input 
    id="fechaCreacion" 
    name="fechaCreacion" 
    type="text" 
    ng-model="seguro.fechaCreacion" 
    ca-datepicker="dd/mm/yy" 
/>

Veamos ahora como es la definición de la directiva:

app.directive('caDatepicker', [function(dateFormat) {
  return {
    restrict: 'A',
    link: function($scope, element, attributes) {
    
      element.datepicker({
        dateFormat: attributes.caDatepicker
      });
    }
  };
}]);

Si usáramos la directiva veríamos que aparentemente funciona pero si añadiéramos el siguiente código HTML a la página:

{{seguro.fechaCreacion}}

comprobaríamos que al cambiar la fecha con el ratón pinchando en el datepick no se cambia el texto de la expresión {{seguro.fechaCreacion}}.

¿Que ha pasado?

Que AngularJS no se ha enterado que le han cambiado el dato dentro de <input> ya que ha sido un evento externo a él así que la propiedad $scope.seguro.fechaCreacion no se ha modificado.

La solución a esto la tenemos en el propio datepicker que provee de un evento que se activa cuando él cambia la fecha. Este evento se llama onSelect.

Para poder usar el evento onSelect solo tenemos que añadir un nueva nueva propiedad llamada onSelect con una función que se llamará cuando se cambie la fecha. En esa función el objeto this hace referencia al propio tag <input>. Dentro de esa función solo tendremos que lanzar el evento onChange de que algo ha cambiado en el <input> y AngularJS ya se enterará.

La directiva ahora queda de la siguiente forma:

app.directive('caDatepicker', [function(dateFormat) {
  return {
    restrict: 'A',
    link: function($scope, element, attributes) {
    
      element.datepicker({
        dateFormat: attributes.caDatepicker,
        onSelect: function() {
          $(this).trigger('change');
        }
      });
    }
  };
}]);

La directiva realmente está sin acabar ya que también debería de transformar el dato de tipo String del <input> en un objeto Date cuando se guarda en $scope.seguro.fechaCreacion. Es decir que $scope.seguro.fechaCreacion debería ser de tipo Date en vez de tipo String. Eso ya lo veremos en la unidad 00_start.

Ejemplo

Referencias