Pregunta

He estado buscando un selector de fecha adecuado para AngularJS y me decidí por usar Pickadate.js

http://amsul.ca/pickadate.js/

debido a su hermosa interfaz de usuario móvil junto con una directiva personalizada para permitir la integración angular como se muestra en esta publicación de blog

http://www.codinginsight.com/angularjs-and-pickadate/

Quería ampliar la directiva en la publicación de blog anterior con un evento para llamar a una función en mi controlador cuando cambia el valor.El código completo de la directiva extendida se muestra a continuación.

angular.module('plunker').directive('pickADate', function () {
    return {
        restrict: "A",
        scope: {
            pickADate: '=',
            minDate: '=',
            maxDate: '=',
            change: '='
        },
        link: function (scope, element, attrs) {
            element.pickadate({
                onSet: function (e) {
                    if (scope.$$phase || scope.$root.$$phase) // we are coming from $watch or link setup
                        return;
                    var select = element.pickadate('picker').get('select'); // selected date
                    scope.$apply(function () {
                        if (e.hasOwnProperty('clear')) {
                            scope.pickADate = null;
                            return;
                        }
                        if (!scope.pickADate)
                            scope.pickADate = new Date(0);
                        scope.pickADate.setYear(select.obj.getFullYear());
                        // Interesting: getYear returns only since 1900. Use getFullYear instead.
                        // It took me half a day to figure that our. Ironically setYear()
                        // (not setFullYear, duh) accepts the actual year A.D.
                        // So as I got the $#%^ 114 and set it, guess what, I was transported to ancient Rome 114 A.D.
                        // That's it I'm done being a programmer, I'd rather go serve Emperor Trajan as a sex slave.
                        scope.pickADate.setMonth(select.obj.getMonth());
                        scope.pickADate.setDate(select.obj.getDate());
                    });
                },
                onClose: function () {
                    element.blur();
                }
            });
            function updateValue(newValue) {
                if (newValue) {
                    scope.pickADate = (newValue instanceof Date) ? newValue : new Date(newValue);
                    // needs to be in milliseconds
                    element.pickadate('picker').set('select', scope.pickADate.getTime());
                } else {
                    element.pickadate('picker').clear();
                    scope.pickADate = null;
                }
            }
            updateValue(scope.pickADate);
            element.pickadate('picker').set('min', scope.minDate ? scope.minDate : false);
            element.pickadate('picker').set('max', scope.maxDate ? scope.maxDate : false);
            scope.$watch('pickADate', function (newValue, oldValue) {
                if (newValue == oldValue)
                    return;
                updateValue(newValue);

                // call change function
                scope.change;
            }, true);
            scope.$watch('minDate', function (newValue, oldValue) {
                element.pickadate('picker').set('min', newValue ? newValue : false);
            }, true);
            scope.$watch('maxDate', function (newValue, oldValue) {
                element.pickadate('picker').set('max', newValue ? newValue : false);
            }, true);
        }
    };
});

Ahora puedo usar esta directiva con el evento de cambio como se muestra a continuación en mi HTML

<input type="text" pick-a-date="curDate" change="onChange()" />

Funciona, pero el evento OnChange se activa varias veces para un solo cambio.¿Alguna idea de cómo puedo hacer que se dispare solo una vez?He creado un plunker para demostrar el problema.

http://plnkr.co/edit/3NcaAknd4GpelJxHWUyv

Haga clic en el campo de texto y seleccione una fecha.Verá que la variable del contador se actualiza varias veces para un solo cambio de fecha.

¿Fue útil?

Solución

Como @miqid sugirió vincular una función entre una directiva y un uso de controlador '&' ('=' debe usarse solo para vincular variables de alcance entre la directiva y el controlador).

También hay un cambio más que se debe realizar en su código actual.La función alcance.cambio en updateValue() no se ejecuta porque se hace referencia a él como alcance.cambio.Esto tiene que cambiarse a scope.change().

Bifurqué su plunker y lo modifiqué para corregir los cambios anteriores.

Plunker de trabajo fijo: http://plnkr.co/edit/oEpOxE21dXre28FpKoMc?p=preview

El contador se actualiza solo una vez para variar.Déjeme saber si esto ayuda.

Otros consejos

Usted ha encado a change dentro de su directiva pick-a-date usando '=' en lugar de '&'.

Se recomienda el Último Ajuste de Aislamiento de Aislado para expresiones como funciones de devolución de llamada.

Asesoramiento relevante de la documentación de AngularJS en Directivas :

Mejor práctica: Use GeneracDicetAnDode en la opción de alcance cuando desea que su directiva exponga una API para la obligación a los comportamientos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top