Jest to całkiem dobre pytanie, a ja odpowiadałem, mimo że już zaakceptowane :)
W kątowy zakres $ jest model. Model jest miejscem przechowywania danych, które możesz chcieć utrwalić lub wykorzystać w innych częściach aplikacji, i jako taki powinien być zaprojektowany z dobrym schematem, tak jak na przykład w bazie danych.
Twój model ma dwa pola redundantne dla temperatury, co nie jest dobrym pomysłem. Który z nich jest "prawdziwą" temperaturą? Są chwile, kiedy chcesz zdenormalizować model, tylko dla wydajności dostępu, ale jest to naprawdę tylko opcja, gdy wartości są idempotentne, co jak zauważyłeś, nie wynikają one z precyzji zmiennoprzecinkowej.
Jeśli chcesz nadal korzystać z modelu, wyglądałoby to tak. Wybrałbyś jedną lub drugą jako temperaturę "źródła prawdy", a następnie wprowadziłeś inne dane jako pole wprowadzania wygody za pomocą formatera i analizatora składni. Powiedzmy, że chcemy Fahrenheita w modelu
<input type="number" ng-model="temperatureF">
<input type="number" ng-model="temperatureF" fahrenheit-to-celcius>
i dyrektywa konwersji:
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;
});
}
};
});
Dzięki temu, można uniknąć „podskakują wokół”, ponieważ $ parser uruchomić tylko na działania użytkownika, a nie w sprawie zmian modelu. Wciąż masz długie miejsca dziesiętne, ale można to naprawić zaokrąglając.
Jednak dla mnie brzmi to tak, jakby nie używać tego modelu. Jeśli wszystko, czego chcesz, to "każde pudełko aktualizuje drugie pudełko", możesz zrobić dokładnie to, a nawet nie mieć modelu. Zakłada to, że pola wejściowe zaczynają się puste i jest to po prostu proste narzędzie do konwersji temperatury przez użytkowników. Jeśli tak jest, nie masz modelu, nie ma kontrolera, a nawet nie używasz Angulara w ogóle. W tym momencie jest to widżet oparty wyłącznie na widoku i jest to w zasadzie po prostu jQuery lub jQLite. Ma jednak ograniczoną przydatność, ponieważ bez modelu nie może wpływać na nic innego w Angular.
Aby to zrobić, wystarczy wprowadzić dyrektywę temperatureConverter
, która ma szablon z kilkoma polami wprowadzania danych, i obserwuje oba pola i ustawia ich wartości. Coś jak:
fahrenheitBox.bind('change', function() {
celciusBox.val((Number(fahrenheitBox.val()) - 32) * 5.0/9.0);
});
Powodem tego jest dobre pytanie, ponieważ ta sytuacja ma nieskończoną pętlę - jeśli obliczenia nie były odwrotne względem siebie ... +1. I będę zaskoczony, widząc inne, różniące się odpowiedzi. – rGil
Ze względu na tło w DSP trudno mi się oprzeć wchodzącemu w to w matematyce, więc po prostu się poddam: Jest możliwe, że to wejdzie w nieskończoną pętlę (z wyjątkiem tego, że Angular ma wbudowany limit max. iteracji). Oto wspaniałe wyjaśnienie, dlaczego wartości "odbijają się" w ogóle (ze względu na brudne sprawdzanie): http://stackoverflow.com/a/9693933/885163. A w połączeniu z ograniczoną precyzją punktu zmiennoprzecinkowego możliwe jest, aby wartości oscylowały 0, 1 lub więcej razy, nawet w nieskończoność, efekt znany jako "cykl graniczny" w filtrach DSR IIR. * uff * jak to dla komentarza? –