Questa è una buona domanda e sto rispondendo che anche se è già accettata :)
Nel angolare, il $ ambito è il modello. Il modello è un luogo in cui archiviare i dati che potresti voler conservare o utilizzare in altre parti dell'app e, come tale, dovrebbe essere progettato con uno schema valido, proprio come faresti per esempio in un database.
Il modello ha due campi ridondanti per la temperatura, che non è una buona idea. Qual è la temperatura "reale"? Ci sono volte in cui vuoi denormalizzare un modello, solo per l'efficienza dell'accesso, ma questa è solo un'opzione quando i valori sono idempotenti, che come hai trovato, non sono dovuti alla precisione in virgola mobile.
Se si desidera continuare a utilizzare il modello, sarebbe simile a questo. Sceglieresti l'uno o l'altro come la "fonte di verità" della temperatura, poi avrai l'altro input come una comoda entry box con un formattatore e un parser. Diciamo che vogliamo Fahrenheit nel modello:
<input type="number" ng-model="temperatureF">
<input type="number" ng-model="temperatureF" fahrenheit-to-celcius>
e la direttiva di conversione:
someModule.directive('fahrenheitToCelcius', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$formatters.push(function(f) {
return (value - 32) * 5.0/9.0;
});
ngModel.$parsers.push(function(c) {
return c * 9.0/5.0 + 32;
});
}
};
});
Con questo, devi evitare il "rimbalza", perché $ parser eseguiti solo su azione dell'utente, non sui cambiamenti del modello. Avresti ancora lunghi decimali, ma questo potrebbe essere risolto con arrotondamenti.
Tuttavia, mi sembra che non dovresti usare un modello per questo. Se tutto ciò che vuoi è "ogni casella aggiorna l'altra casella", puoi fare esattamente questo e non avere nemmeno un modello. Ciò presuppone che le caselle di input inizino in bianco e che sia solo uno strumento semplice per convertire le temperature. Se questo è il caso, non hai alcun modello, nessun controller e non usi nemmeno quasi nulla. A quel punto è un widget basato esclusivamente sulla vista, ed è fondamentalmente solo jQuery o jQLite. È tuttavia di utilità limitata, poiché senza modello non può effettuare alcun effetto su Angular.
Per fare ciò, è sufficiente creare una direttiva temperatureConverter
che abbia un modello con un paio di caselle di input e che guardi entrambe le caselle e ne imposti i valori. Qualcosa del tipo:
fahrenheitBox.bind('change', function() {
celciusBox.val((Number(fahrenheitBox.val()) - 32) * 5.0/9.0);
});
Il motivo per cui questa è una buona domanda è perché questa situazione ha un ciclo infinito dappertutto - se i calcoli non erano inversi l'uno dell'altro ... +1. E sarò sorpreso di vedere altre risposte diverse. – rGil
A causa di uno sfondo in DSP, è difficile per me resistere alla matematica, quindi mi limiterò a rinunciare: è possibile che questo entri in un loop infinito (eccetto che Angular ha un built-in limite di iterazioni massime). Ecco una grande spiegazione del perché i valori "rimbalzano" a tutti (a causa del controllo sporco): http://stackoverflow.com/a/9693933/885163. E quando accoppiato con la precisione limitata del punto mobile, è possibile che i valori oscillino 0, 1 o più volte, anche indefinitamente, un effetto noto come "ciclo limite" nei filtri DSP IIR. * phew * com'è questo per un commento? –