Dailycode.info

Short solution for short problems

AngularJS: Single quotes in a directive template and method binding inside ng-repeat. (all in 1)

I have a directive that creates a button inside a ng-repeat. The button has a ng-click and also ng-class attribute where the class is set based on a value of the model. the ng-click calls a function on the scope of the parent controller and is passed by an attribute to the scope of the directive.

So the HTML code looks like this:

<div class="panel-body" data-ng-repeat="player in players">
    <div player-button="player" on-click="selectPlayer(player)" ></div>
</div>

And the directive looks like this:

.directive('playerButton', function() {
    return {
        scope: { player: '=playerButton', onClick: '&' },
        template: '<button class="btn btn-default input-block-level form-control" ng-click="onClick({player : player})" ng-class="{true : \'btn btn-primary input-block-level form-control\', false : \'btn btn-default input-block-level form-control\' }[player.number > 0]"><div ng-if="player.number != 0" class="label label-info">{{player.number}}</div>&nbsp;{{player.text}}</button>',
    }
})

You see that I had to escape the ' with \' inside the ng-class attribute. I also bind the selectedPlayer(player) to the onClick and pass this. The player from the scope is used because its inside the ng-repeat and it cannot be just the player from the parent scope.



AngularJS: Directive that show the number in red if < 0, green > 0 and black == 0

I have a game where scores are shown in multiple places. The score text should turn red when the score is below zero, green when the score is positive and black when the score is 0. 

Directives make this very easy. 

This directive does the trick:

.directive('valueColor', [
function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs) {

            scope.$watch(attrs.ngModel, function (newValue)
            {
                console.log(newValue);
                var test = parseInt(newValue);

                if (test > 0) {
                    element.css('color', 'green');
                }
                else if (test < 0) {
                    element.css('color', 'red');
                }
                else if (test == 0) {
                    element.css('color', 'black');
                }
                else { console.log('Nan value: ',test);}
            });
        }
    }
}
])

So based on the ng-model value, I change the color of the containing text. The html code only shows this:

<tr class="row">
    <td class="col-md-2">Totaal</td>
    <td class="col-md-2">
        <h3 value-color ng-model="player1.total">{{player1.total}}</h3>
    </td>
    <td class="col-md-2">
        <h3 value-color ng-model="player2.total">{{player2.total}}</h3>
    </td>
    <td class="col-md-2">
        <h3 value-color ng-model="player3.total">{{player3.total}}</h3>
    </td>
    <td class="col-md-2">
        <h3 value-color ng-model="player4.total">{{player4.total}}</h3>
    </td>
</tr>

So you add the directive value-color and the ng-model to the DOM element and it works.

Using directives can clean up your code and improve the maintainability of your app! If I want to do something different with the score, it is very likely that I only have to change the directive and everywhere this change is applied.



AngularJS: Access rootScope in Directive

I made a directive that based on a model change would need do do some calculations on an object on the root scope.

So to access the rootScope, simply use this:

scope.$root.

Then you can access any object in the rootScope. Very powerfull!

Here's the complete directive I've written. This will calculate for a row if the total is not higher then a 'attubute set' number, of higer or some input is not a number, then the row ill appear in red. If lower, then the row will stay white, if equal, it will turn green.

.directive('maxRowValue', [
function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            scope.$watch(function () {
                return ngModel.$modelValue;
            }, function (newValue) {

                var totalRow = 0;
                var goOn = true;
                for (var i = 0 ; i < 4; i++) {
                    if (!isNaN(parseInt(scope.$root.game.scores[attrs.rowNumber][i]))) {
                        totalRow += parseInt(scope.$root.game.scores[attrs.rowNumber][i]);
                    }
                    else {
                        console.log('Nan value inserted');
                        goOn = false;
                        break;
                    }
                }

                if (goOn == true && totalRow < attrs.rowValue)
                {
                    console.log('OK');
                    element.css('background', 'white');
                }
                else if (goOn == true && totalRow == attrs.rowValue)
                {
                    console.log('Complete');
                    element.css('background', 'green');
                }
                else
                {
                    console.log('Row values not correct');
                    element.css('background', 'red');
                }
            });
        }
    }
}
])

So this works nice, you can check this working at my new project DailyCardGames.

Just to show here's a screen shot:



AngularJS: Set ng-style text decoration

I was trying to set the text decoration from the controller to underlined or none, depending on some scope variable.

<row ng-style="{text-decoration: player1.turn}"><h2>{{player1.text}}</h2></row>

But first I got some errors: Error: [$parse:syntax] Syntax Error: Token '-' is unexpected, expecting [:] at column 6 of the expression [{text-decoration:

 Now I found why:

<row ng-style="{'text-decoration': player1.turn}"><h2>{{player1.text}}</h2></row>

I needed to put text-decoration between quotes. player.turn can hold none, underlined or any other decoration.