質問

I have a repeater that renders gridBlocks. Each of these blocks has a property for "Vote Good", "Vote Bad" or "No vote" (for our purpose). This property controls, among other things, the CSS class of the block.

The data structure for the user vote is accessed via userService, which exposes methods for updating the votes, doing the ajax calls etc.

My problem is this:

I'm setting the voteClass property in the scope of each specific block via a call to the userService. I would like to watch this property and update the UI accordingly when its model changes.

However this does not seem to work - the voteClass doesn't re-evaluate and $watch isn't called even though the value for getVoteClass(scope.block.id) does indeed change.

I've tried using $apply, but that didn't seem to change anything.

I would very much appreciate your input...

Update1 :I think that even though the value for getVoteClass(scope.block.id) changes, the block scope property does not. Is there any way to force the block scope to re-evaluate its properties?

Update 2 - Problem solved: With the help of CaioToOn and Gloopy on this question I realized that the fault lies with the fact that the scope property was referencing a primitive string. To overcome this, you can either watch a function, or use a direct reference to an object property (and not a primitive string).


Controller:

    var gridController=['$scope', "userService", function($scope, userService) {

        $http.get(url).success(function(data) {
            $scope.blocks = data;
        });

        $scope.getLookVoteStatus = userService.getLookVoteStatus

    }];

Directive:

.directive('gridBlock', function() {
        return {
            link: function(scope, element, attrs) {

                scope.voteClass=getVoteClass(scope.block.id);
                scope.$watch('voteClass',function(newValue, oldValue) {                                                
                    element.addClass(newValue);
                });

             }
        }
    });
役に立ちましたか?

解決

The voteClass is not changing after the first call, although the return for getVoteClass is, but it does not get called again.

To not change your example, the right way to go would be:

function checkForVoteClass() {
  return getVoteClass(scope.block.id);
}

scope.$watch(checkForVoteClass,function(newValue, oldValue) {                                                
  element.addClass(newValue);
})

But have in mind that everytime an $apply occur anywhere in the system, this is going to get reevaluated.

So, when getVoteClass would return a different value? On user interaction? If it is, then the best way to go should be something like this:

<span ng-click="vote='bad'">Bad</span>
<span ng-click="vote='good'">Good</span>
<span id="thisIsYourElement" 
  ng-class="{bad: 'badCssClass', good: 'goodCssClass', 'undefined': 'noVoteClass'}[vote]"
  >Your content</span>

Of course, its pretty simplified.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top