Undefined property value in directive nested in ng-repeat

138 views Asked by At

I am new to angular and I have searched intensively for a resolution to this issue but I can't quite seem to figure it out.

I have myRating directive that is nested in ng-repeat and that is nested in google maps api directive, html below:

<ui-gmap-google-map center='map.center' zoom='map.zoom'>
    <ui-gmap-search-box template="searchbox.template" events="searchbox.events"></ui-gmap-search-box>
<ui-gmap-marker ng-repeat="marker in markers" click="marker.click" coords="marker" idKey="$index" icon="marker.icon"
                events="marker.events">
    <ui-gmap-window isIconVisibleOnClick="true" show="marker.showWindow" zIndex="">
        <p class="gm-tooltip">
            <a class="gm-name" href="{{marker.url}}">
                {{marker.name}}<br>
                <my-rating rating-value="marker.rating" max="5" read-only="true"></my-rating>
            </a>
        </p>
    </ui-gmap-window>
</ui-gmap-marker>

Directive code:

angular.module('foodMap.directives')
.directive('myRating', function () {
    return {
        restrict: 'E',
        template: '<div class="rating" ng-class="{readonly: readOnly}">' +
        '<span ng-repeat="star in stars" class="star {{star.reverseIndex}}" ng-class="{fullstar: star.reverseIndex==ratingValue}" ng-click="toggle(star.reverseIndex, $event)"></span>' +
        '</div>',
        scope: {
            ratingValue: '=',
            max: '=',
            readOnly: '@'
        },
        link: function (scope, element, attrs) {
            scope.stars = [];

            for (var i = scope.max; i > 0; i--) {
                scope.stars.push({reverseIndex: i});
            }

            scope.toggle = function (reverseIndex, event) {

                if (scope.readOnly)
                    return;

                scope.ratingValue = reverseIndex;

                //jQuery to remove
                $('.star').removeClass('fullstar');
                $(event.target).toggleClass('fullstar');
            };
        }
    }
});

Controller

angular.module('foodMap.controllers')
.controller('MainCtrl', [
    '$scope',
    'bites',
    function ($scope, bites) {
        $scope.bites = bites.bites;
        $scope.map = {
            center: {
                latitude: 51.5286416,
                longitude: -0.1015987
            },
            zoom: 11
        };

        $scope.markers = [];

        var createMarker = function (bite){

            var marker = {
                latitude: bite.location[0],
                longitude: bite.location[1],
                name: bite.name,
                address: '',
                icon: 'images/markers/restaurant.png',
                url: '/#/bites/' + bite._id,
                rating: bite.rating,
                showWindow: false,
                click: function() {
                    //not sure if this is the best solution
                    _.each($scope.markers, function(marker) {
                        marker.showWindow = false;
                    });
                    marker.showWindow = true;
                }
            }

            $scope.markers.push(marker);

        }

        for (var i = 0; i < $scope.bites.length; i++){
            createMarker($scope.bites[i]);
        }


        var events = {
            places_changed: function (searchBox) {
                var places = searchBox.getPlaces();
                if (places) {
                    var lat = places[0].geometry.location.lat();
                    var lng = places[0].geometry.location.lng();

                    $scope.map.center.latitude = lat;
                    $scope.map.center.longitude = lng;
                    var address = places[0].address_components[0] && places[0].address_components[0].short_name || '';
                    var marker = {
                        latitude: lat,
                        longitude: lng,
                        name: places[0].name,
                        address: address,
                        icon: 'images/markers/star-3.png',
                        url: '/#/bites/',
                        rating: 5,
                        showWindow: true
                    }

                    $scope.markers.push(marker);

                    $scope.map.zoom = 15;
                }
            }
        }

        $scope.searchbox = { template:'searchbox.tpl.html', events: events };

    }
]);

So the problem is that that currently I have 3 markers in my db and ng-repeat loops through the collection twice so myRating directive is called 6 times. When I console.log(ratingValue), during the first loop the values are correct, but when it loops the second time all ratingValue values are undefined.
From all the research I have done, as far as I understand, angular performs dirty-checking to figure out what has changed, so that's why two loops? But I don't understand why I'm loosing these values that are bind correctly in the first loop.

Sorry, I hope that is clear enough, I would appreciate any pointers!

0

There are 0 answers