Reputation: 25097
I have a series of input fields that are all bound to properties on an AngularJS model that are all editable.
Some of the fields are optionally calculated fields based on the other user input, a sample of the kind of input I'm working with can be found here.
Basically if someone enters a value in the time
and distance
it should automatically work out speed
, or speed
and distance
will work out time, and so on.
Upvotes: 1
Views: 2085
Reputation: 77904
You can write something like that (by using $watch
):
JS
angular.module('app', [])
.controller('Ctrl', function ($scope) {
$scope.mymodel = {};
$scope.mymodel.time = 0;
$scope.mymodel.distance = 0;
$scope.mymodel.speed = 0;
$scope.$watch(function () {
return $scope.mymodel;
},
function (newValue, oldValue) {
$scope.mymodel.speed = (newValue.distance > 0) ? newValue.distance / newValue.time : 0;
}, true);
});
HTML
Time: <input type="number" ng-model="mymodel.time" />
<br />
Distance: <input type="number" ng-model="mymodel.distance" />
<br />
Speed: <input type="number" ng-model="mymodel.speed" />
Comment
Its only example, in this case you can't change velocity (speed).
Changed DEMO
[EDIT]
you can play with $watch
to control sub-fields:
$scope.$watch(function () {
return $scope.mymodel;
},
function (newValue, oldValue) {
if(newValue.speed != oldValue.speed){
$scope.mymodel.time = newValue.distance / newValue.speed;
$scope.mymodel.distance =newValue.time *newValue.speed;
}
else if(newValue.distance != oldValue.distance){
$scope.mymodel.speed = (newValue.distance > 0) ? newValue.distance / newValue.time : 0;
}
else if(newValue.time != oldValue.time){
$scope.mymodel.speed = (newValue.distance > 0) ? newValue.distance / newValue.time : 0;
}
}, true);
Upvotes: 1
Reputation: 34288
The problem is underspecified since what if all the three values are specified by the user and he changes one of them? I took a guess and decided to change the last value which was touched by the user, keeping the recent two values constant.
I think it can be generalised for pretty much any formula, but your milage may vary. It was amusing to write. :)
Here is a working example: http://jsbin.com/OsuMaSek/1/edit
$scope.time = 0;
$scope.distance = 0;
$scope.speed = 0;
$scope.touchOrder = {
speed: 0,
distance: 0,
time: 0
};
function getLastTouched() {
var minTouched = null, minVal = Infinity;
Object.keys($scope.touchOrder).forEach(function (k) {
if (minVal > $scope.touchOrder[k]) {
minVal = $scope.touchOrder[k];
minTouched = k;
}
});
return minTouched;
}
$scope.totalTouchCount = 0;
$scope.touched = function (valTouched) {
$scope.totalTouchCount++;
$scope.touchOrder[valTouched] = $scope.totalTouchCount;
if ($scope.totalTouchCount >= 2) {
switch(getLastTouched()) {
case 'time': $scope.time = $scope.distance / $scope.speed; break;
case 'distance': $scope.distance = $scope.time * $scope.speed; break;
case 'speed': $scope.speed = $scope.distance / $scope.time; break;
}
}
};
Upvotes: 5