简体   繁体   中英

angularjs - dynamic function return

index.html

<div ng-repeat="object in objects" ng-style="getStyle(object.id)"></div>

controller.js

[...]

$scope.startWidth = 100;

$scope.getObject = [...]

$scope.getStyle = function(id) {
   var widthVal = $scope.startWidth;
   $scope.StartWidth += $scope.getObject(id).value;
   return { width : widthVal }
}

[...]

This code runs into an infinite $digest loop. I think i know why. The return value should not to be dynamic. But how can i realize that without the loop? I want to display objects with different width. The width of an object depends on a value of the previous object.

The problem is that ng-style puts a $watchExpression on each child scope.

A $watchExpression must be idempotent , means it must return the same with multiple checks.
If a $watchExpression is still dirty another $digest will be triggered.

UPDATE

After I saw GRaAL nice answer I came up with even better solution:

Here is a demo plunker: http://plnkr.co/edit/oPrTiwTOyCR3khs2iVga?p=preview

controller:

$scope.$watchCollection('objects', function calculateWidths() {
  var tempWidth = 0;
  for( var i = 0; i < $scope.objects.length; i++) {
    tempWidth += $scope.objects[i].value;
    $scope.objects[i].width = tempWidth + 'px';
  }
});

markup:

<div ng-repeat="object in objects" ng-style="{width: object.width}">

old solution

Here is a plunker: http://plnkr.co/edit/CqxOmV5lpZSLKxqT4yqo?p=preview

I agree with Ilan's problem description and solution - it works in case the objects array is not going to change, otherwise the widths will be calculated incorrectly. If new objects may be added/removed in runtime then it is better to recalculate the widths when the collection is changed (see $watchCollection method of scope) or on each digest cycle (for short list of elements it shall be fast enough), something like that:

  var widths = [];
  $scope.$watch(function calculateWidths() {
    var tempWidth = 0;
    widths = [];
    angular.forEach($scope.objects, function(obj) {
      tempWidth += obj.value;
      widths.push(tempWidth);
    });
  });

  $scope.getStyle = function(idx){
    return {width: widths[idx] + 'px'}
  }

Here is the plunker

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM