JSFiddle - React, Tailwind, and code Playground

by Garth Edwards

HTML

<script src="https://code.angularjs.org/1.3.5/angular.js"></script>
<body ng-app="myApp">
    <div ng-controller="RatingsController">
        Artist Ratings<br>
        {{artistRatings.current}} out of {{artistRatings.max}}
        <div artist-rating rating-value="artistRatings.current" max="artistRatings.max" on-rating-selected="artistSelectedRating(rating)"></div>
        <br>
        Venue Ratings<br>
        {{venueRatings.current}} out of {{venueRatings.max}}
        <div artist-rating rating-value="venueRatings.current" max="venueRatings.max" on-rating-selected="venueSelectedRating(rating)"></div>
    </div>
</body>

CSS

.pref-filter-button {
	display: inline-block;
	width: 8%;
	height: 0;
	padding-bottom: 8%;
	margin: -1px 4px 0 0;
	vertical-align: middle;
	background: #343434;
	display: inline-block;
	cursor: pointer;
	margin-bottom: 10px;
	vertical-align: text-top;
}
.pref-filter-button.active{
	background: #9d0e11;
	display: inline-block;
	margin-bottom: 10px;
	vertical-align: text-top;
}

JavaScript

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

myApp.controller('RatingsController', ['$scope', function ($scope) {
    $scope.rating = 0;
    $scope.artistRatings = {
        current: 1,            // this is the initial 'current' rating
        max: 10                // this is the maximum (ie rating out of 10
    };
    $scope.venueRatings = {
        current: 5,            // this is the initial 'current' rating
        max: 10                // this is the maximum (ie rating out of 10
    };
    
    
    $scope.artistSelectedRating = function (rating) {
        console.log('artistRatings.current', rating);
    };
    $scope.venueSelectedRating = function (rating) {
        console.log('venueRatings.current', rating);
        $scope.artistRatings.current= rating;        //this is just a test to show that a change in .current results in an immediate update of the graphic
    };
}]);

myApp.directive('artistRating', function () {
    return {
        restrict: 'A',                // means directive is added to element as a attribute in snake case eg. "<div artist-rating></div>"
        template:                     // template is added in the element which has the attribute added
                '<li ng-repeat="star in stars" class="pref-filter-button" ng-class="star" ng-click="toggle($index)"></li>', 
        scope: {
            ratingValue: '=',                // = means two way data binding between $scope and this directives 'isolated scope' 
            max: '=',
            onRatingSelected: '&'
        },
        link: function (scope, elem, attrs) {

            var updateRatings = function () {
                scope.stars = [];
                for (var i = 0; i < scope.max; i++) {
                    scope.stars.push({
                        active: i < scope.ratingValue
                    });
                }
            };

            scope.toggle = function (index) {            // function expression called "toggle" (not a generic ng - ie. a made up...