I have part of a web page that shows each teams name and score and it has two buttons for each team (Score -1, and Score +1).
Teams is an array and the teams are shown using an ng-repeat.
<!-- Teams Info & Control -->
<div class="row center-text" style="height: 40%;">
<div class="col" ng-repeat="team in game.teams">
<h5 style="display: inline;">{{team.name}}</h5>
<i class="fa fa-edit" ng-click="editTeamName($index)" class="btn btn-link"></i>
<h6>{{team.score}}</h6>
<div class="row">
<div class="col">
<button type="button" ng-click="scoreChange($index, -1)" class="btn btn-primary fill-height fill-width">Score -1</button>
</div>
<div class="col">
<button type="button" ng-click="scoreChange($index, 1)" class="btn btn-primary fill-height fill-width">Score +1</button>
</div>
</div>
</div>
</div>
The teams array is part of a larger object called "game" this object is received 10 times per second from a socket.io server. It needs to be 10 times per second because there is a timer in the game object that needs to be displayed to the user with high accuracy.
How the game object is updated on the client side:
socket.on('gameUpdate', function(game) {
$scope.$apply(function() {
$scope.game = game
});
});
Sample game object:
{
gameRunning: false,
shotClockTime: defaultFullShotClock, //Value changing 10 times per second other values may change too but not as frequently
oldShotClockValue: defaultFullShotClock,
teams: [{
name: "White",
score: 0
}, {
name: "Blue",
score: 0
}],
inOvertime: false,
currentPeriod: 0,
periods: {
mainGame: generateMainGame(defaultPeriodTime, defaultBreakTime, defaultHalfTime),
overtime: generateOverTime(defaultOverTimePeriodTime, defaultBreakTime)
}
}
When the game object changes, the teams display HTML is updated ($$!) even though no changes have been made to the teams array itself. The problem is that a mouse-down then mouse-up event usually takes longer than 0.1 seconds meaning that they will not happen to the same button so they are not registered as a click meaning that the ng-click is not called.
$$! (I think this is happening because in inspect element that section is flashing purple. Also, the button color, when hovered over, is rapidly alternating between the hover and default colors. Video)
Use the track by clause in your ng-repeat like:
<div class="col" ng-repeat="team in game.teams track by $index">
Track by is a useful clause that does a few things, but one of them is that it lets angular track which items are in a list so that it knows which ones need to be rerendered or which already exist. However, if these items are from database and have a unique identifier, it's actually better to use that property as the tracker rather than the index as it performs better and allows for reordering:
<div class="col" ng-repeat="team in game.teams track by team.id">