Search code examples
angularjsangular-schema-form

Computed values in angular-schema-form


I have a form which is used to enter a bunch of values. I want to show various calculation on the values, but dynamically, so that when a number is changed the results immediately update. I thought that this should work, but it doesn't - i.e. the calculation is never run:

angular.module('calcs', ['schemaForm'])
  .controller('CalcCtrl', function ($scope) {
    $scope.schema = {
      type: 'object',
      properties: {
        width: {
          type: 'number',
          title: 'Width'
        },
        depth: {
          type: 'number',
          title: 'Depth'
        }
      }
    };
    $scope.form = ['*'];
    $scope.model = {};

    $scope.$watch('[model.width, model.depth]', function() {
      // This function is never called
      $scope.area = $scope.model.width * $scope.model.depth;
    });
  });

I have seen this question, but I am doing quite a number of calculations and I really don't want to have to create a directive for each, so I am hoping there is another way. For reference, here is my template:

<div ng-controller="CalcCtrl">
  <form sf-schema="schema" sf-form="form" sf-model="model"></form>
  <p>Area: {{area}}</p>
</div>

Solution

  • I believe what you want is $watchCollection:

    $scope.$watchCollection('[model.width, model.depth]', function() {
      // This function is never called
      $scope.area = $scope.model.width * $scope.model.depth;
    });
    

    example:

    var app = angular.module('app', []);
    
    app.controller('myController', function($scope) {
    
      $scope.model = {}
      
      $scope.$watchCollection('[model.width,model.height]', function() {
        $scope.area = $scope.model.width * $scope.model.height;
      });
      
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="app">
      <div ng-controller="myController">
        <input ng-model="model.width">
        <input ng-model="model.height">
        {{area || ''}}
      </div>
    <div>