ANGULARJS Data Picker Fireing OnCange Event molteplici volte
-
20-12-2019 - |
Domanda
Ho cercato un raccoglitore di date adatto per AngularJs e sistemato sull'uso pickadate.js
A causa del suo bell'interfaccia utente mobile insieme a una direttiva personalizzata per consentire l'integrazione angolare come mostrato in questo post del blog
http://www.codinginsight.com/angularjs-and-pickadate/
Volevo estendere la direttiva nel post del blog sopra con un evento per chiamare una funzione nel mio controller quando il valore cambia. Il codice completo per la direttiva estesa è mostrata sotto
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);
}
};
});
.
Posso ora utilizzare questa direttiva con Modifica evento come mostrato di seguito nel mio HTML
<input type="text" pick-a-date="curDate" change="onChange()" />
.
funziona ma l'evento di onchange viene licenziato più volte per un singolo cambiamento. Qualche idea su come posso farcela per sparare solo una volta? Ho creato un pinkeer per dimostrare il problema
http://plnkr.co/edit/3ncaaknd4gpeljxhwuyv
Fare clic sul campo di testo e selezionare una data. Vedrete la variabile contatore viene aggiornata più volte per un cambio singolo data.
Soluzione
AS @MIQID ha suggerito di assistere a una funzione tra la direttiva e un controller utilizzare '&'
('='
deve essere utilizzato solo per le variabili di ambito vincolante tra Direttiva e Controller.)
Inoltre c'è un altro cambiamento che deve essere fatto al tuo codice corrente.La funzione Scope.Change in updateValue()
non viene eseguita in quanto è stata referenziata come scope.Change.Questo deve essere cambiato in scope.change()
.
Ho biforcuto il blocker e lo ha modificato per risolvere le modifiche sopra indicate.
Plunker di lavoro fisso: http://plnkr.co/edit/oepoxe21dxre28fpkomc?p=preview
Il contatore viene aggiornato solo una volta per un cambiamento.Fammi sapere se questo aiuta.
Altri suggerimenti
Hai legato change
all'interno della direttiva pick-a-date
utilizzando '='
anziché '&'
.
Quest'ultimo legame dell'ambito dell'isolato è raccomandato per le espressioni come le funzioni di callback.
Consigli pertinenti della documentazione angolarejs su Direttive :
.Best Practice: Utilizzare
&attr
nell'opzione Ambito quando si desidera che la tua direttiva esporre un'API per vincolante ai comportamenti.