Aaron Powell
Aaron Powell

Reputation: 25097

Updating AngularJS fields based on other fields

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

Answers (2)

Maxim Shoustin
Maxim Shoustin

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);

Demo 2

Upvotes: 1

musically_ut
musically_ut

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

Related Questions