0

I would like to change which variables to watch.

JS:

var app = angular.module('myApp', []);

app.controller('MainController', 
  function($scope) {
    
    $scope.current = null;
    $scope.select = function(item) {
      $scope.current = item;
    };
    
    var watch = ['current'];
    $scope.$watchGroup(watch, function() {                 // This does not work
      if ($scope.current !== null) {
        watch = ['current'];
        Array.prototype.push.apply(watch, $scope.current.watch);
        $scope.current.callBack();
      }  
    });
    
    $scope.list = [
        {
          name: 'test-A',
          watch: ['a'],
          callBack: function() {
            $scope.value = 2 * $scope.a;
          }
        },
        {
          name: 'test-B',
          watch: ['b'],
          callBack: function() {
            $scope.value = 3 * $scope.b;
          }
        }
      ];
  
});

HTML:

<!DOCTYPE html>
<html ng-app="myApp">

<head>
  <link data-require="[email protected]" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
  <script data-require="jquery" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
  <script data-require="[email protected]" data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <script data-require="[email protected]" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller="MainController">
  <div class="dropdown">
    <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
      {{current != null ? current.name : 'DropDown'}}
      <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
      <li ng-repeat="item in list">
        <a href="javascript:void(0)" ng-click="select(item)">{{item.name}}</a>
      </li>
    </ul>
  </div>
  When "test-A" is selected, result is 2 times of A.
  <br> When "test-B" is selected, result is 3 times of B.

  <br>
  <br>
  <br>

  <form class="form-inline">
    <div class="form-group">
      <label>A</label>
      <input type="text" class="form-control" ng-model="a">
    </div>
    <div class="form-group">
      <label>B</label>
      <input type="text" class="form-control" ng-model="b">
    </div>
  </form>

  <br> result : {{value}}
  <br>
</body>

</html>

This is Plunker example.

The result should be 2 times of A when test-A is selected, should be 3 times of B when test-B is selected.

I would like to update which variables to be watched. But the way shown in the line This does not work does not work. This $watchGroup only fires when current is changed. I would like to fire this $watchGroup when current or a is changed in case test-A is selected, and when current or b is changed in case test-B is selected.

I know $scope.$watchGroup(['a', 'b', 'current'], ... works. But I do not like to fire this $watchGroup when test-A is selected and b is changed and vice versa.

How can I update which variables to be watched?

2 Answers 2

1

find the following code as your answer see if it helps you.

Script

var app = angular.module('myApp', []);

app.controller('MainController', 
  function($scope) {

    $scope.current = null;
    $scope.select = function(item) {
      $scope.current = item;
    };

    var watch = ['current'];
    $scope.$watchGroup(watch, function() {
      if ($scope.current !== null) {
        watch = ['current'];
        Array.prototype.push.apply(watch, $scope.current.watch);
        $scope.current.callBack();
      }  
    });

    $scope.list = [
        {
          name: 'test-A',
          watch: [' is two times of a'],
          callBack: function() {
            $scope.value = (2 * $scope.a) + ($scope.current.watch);
          }
        },
        {
          name: 'test-B',
          watch: [' is three times of b'],
          callBack: function() {
            $scope.value = (3 * $scope.b) + ($scope.current.watch);
          }
        }
      ];

});

I just concatenated ($scope.current.watch) this with your result

See if it forked to your plnkar.

https://plnkr.co/edit/UGPe4lgJPydEeAXOc0xR?p=preview

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for reply, but this does not work as I hope. I would like to fire the watch when a is changed in case test-A is selected, and fire when b is changed in case test-B is selected.
1

Change the line:

$scope.$watchGroup(watch, function() {

as below:

$scope.$watch('current', function() { 

The reason behind this is the current value is changed when you clicked on menu. var watch = ['current']; is different variable and this one is not changed when you click on menu. To work properly watch, you need to point to the correct variable, in your case, $scope.current is the correct variable.

// Code goes here

var app = angular.module('myApp', []);

app.controller('MainController', 
  function($scope) {
    
    $scope.current = null;
    $scope.select = function(item) {
      $scope.current = item;
    };
    
    var watch = ['current'];
    $scope.$watch('current', function() {
      if ($scope.current !== null) {
        watch = ['current'];
        Array.prototype.push.apply(watch, $scope.current.watch);
        $scope.current.callBack();
      }  
    });
    
    $scope.list = [
        {
          name: 'test-A',
          watch: ['a'],
          callBack: function() {
            $scope.value = 2 * $scope.a;
          }
        },
        {
          name: 'test-B',
          watch: ['b'],
          callBack: function() {
            $scope.value = 3 * $scope.b;
          }
        }
      ];
  
});
<!DOCTYPE html>
<html ng-app="myApp">

<head>
  <link data-require="[email protected]" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
  <script data-require="jquery" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
  <script data-require="[email protected]" data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <script data-require="[email protected]" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller="MainController">
  <div class="dropdown">
    <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
      {{current != null ? current.name : 'DropDown'}}
      <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
      <li ng-repeat="item in list">
        <a href="javascript:void(0)" ng-click="select(item)">{{item.name}}</a>
      </li>
    </ul>
  </div>

  <br>

  <form class="form-inline">
    <div class="form-group">
      <label>A</label>
      <input type="text" class="form-control" ng-model="a">
    </div>
    <div class="form-group">
      <label>B</label>
      <input type="text" class="form-control" ng-model="b">
    </div>
  </form>

  <br> result : {{current.watch}}
  <br>
</body>

</html>

4 Comments

Thanks for reply, but this does not work as I hope. I would like to fire the watch when a is changed in case test-A is selected, and fire when b is changed in case test-B is selected.
Check the updated code snippet. If you need other thing, let me know
Sorry this also does not work as I hope. I would like to update the result value when the value A (in case test-A selected) or B (in case test-B) is changed
In which field you want to update, input box? What is the meaning of "When "test-A" is selected, result is 2 times of A. When "test-B" is selected, result is 3 times of B." And if test-A selected 2 times then what is expected?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.