0

I am having two problems with the order that things are happening in angular and the browser. I am using laravel as the backend and the following is happening.

User clicks a link and laravel routes the user to /trainers/all. trainers/all includes html which includes html which includes trainersController and ratingsCtrl. trainerscontroller makes a get request to the server for the trainers json object. ng-repeat loops through this object and displays information for each trainer including an image and their rating.

ratingsCtrl then takes their rating and turns it into a number of stars using angular.ui rating functionality.

The problem is two fold, the browser is requesting the images before angular has put the url slug from the json object into the img object. The browser seems to try multiple times failing until angular has done its work.

The second is that angular tries to take the value of the rating before trainersController has put it in the dom element as well. this second error stops the ng repeat so only one trainer is displayed, if I remove the ratingctrl then the ngrepeat completes with no issues besides the img issue. If I hardcode the rating value it works also.

here is the error

TypeError: undefined is not a function
    at Ia.% (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:145:85)
    at Ia.% (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:145:85)
    at t.constant (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:157:136)
    at Ia.% (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:145:85)
    at t.constant (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:157:136)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:48:165
    at q (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:7:380)
    at E (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:47:289)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:56:32
    at f (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js:42:399) 

here is the relevant code

app.js

var trainercompareapp = angular.module("trainercompare", ['ui.bootstrap']);

trainercompareapp.config(function($interpolateProvider) {
  $interpolateProvider.startSymbol('%%');
  $interpolateProvider.endSymbol('%%');
});

function trainersController($scope, $http) {
     $http.get('/trainers').success(function(trainers) {
        $scope.trainers = trainers;
     });
}

var RatingCtrl = function ($scope) {
  $scope.rate = 7;
  $scope.max = 10;
  $scope.isReadonly = false;

  $scope.hoveringOver = function(value) {
    $scope.overStar = value;
    $scope.percent = 100 * (value / $scope.max);
  };

  $scope.ratingStates = [
    {stateOn: 'glyphicon-ok-sign', stateOff: 'glyphicon-ok-circle'},
    {stateOn: 'glyphicon-star', stateOff: 'glyphicon-star-empty'},
    {stateOn: 'glyphicon-heart', stateOff: 'glyphicon-ban-circle'},
    {stateOn: 'glyphicon-heart'},
    {stateOff: 'glyphicon-off'}
  ];
};

html

<div class="col-xs-12 container" ng-controller="trainersController">
        <div ng-repeat="trainer in trainers">
            <div class="col-xs-6">

                <div class="row">

                    <img class="col-xs-6"src="%% trainer.user.images[0]['s3Url'] %%">

                </div>

                <div class="row">

                    <div class="col-xs-7" ng-controller="RatingCtrl">

                        <rating
                            class="rating" 
                            value="%% trainer.rating %%" 
                            max="max" 
                            readonly="true" 
                            on-hover="hoverOver(value)" 
                            on-leave="overStar = null">
                        </rating>

                    </div>

                    <div class="col-xs-4">
                        <a href="/trainers/%% trainer.id %%">View Profile</a>
                    </div>

                </div>
                    <hr>
            </div>
        </div>
    </div>
Mark
  • 3,137
  • 4
  • 39
  • 76
  • 1
    Are you using ng-src in your image tag? – Gruff Bunny Jan 15 '14 at 12:00
  • Are you using server-side routing with angular.js?? why not using client side routing (ngRoute / ui-router)? – Ilan Frumer Jan 15 '14 at 12:02
  • @gruff I am now thanks that has resolved the images problem – Mark Jan 15 '14 at 12:02
  • @IlanFrumer I am using server side routing. I only started with angular a week or two ago so wanted to use as much of laravel which I am already familiar with as possible. – Mark Jan 15 '14 at 12:04
  • 2
    I think you lost the whole idea of separation between client and server side. You now have your angular.js app totally coupled with laravel. That's bad for development and also bad for performance. The angular way is to consume RESTFul APIs, as opposed to jquery or backbone. Learning angular.js routing is pretty straightforward. Do not fall in to that trap! – Ilan Frumer Jan 15 '14 at 12:24
  • Thank you for the advice I appreciate it however for the immediate future this project is going to be done this way and as described in option 2 of this answer http://stackoverflow.com/questions/18420069/what-application-structure-to-use-with-angularjs-and-laravel so my immediate problem is figuring out how to get the ratingcontroller working properly – Mark Jan 15 '14 at 12:32
  • Ugh, changing value="%% trainer.rating %% to just value="trainer.rating" made it work like a charm if anyone has a link to an explanation of when you need to use ng-bind and when you don't it would be greatly appreciated – Mark Jan 15 '14 at 12:50
  • 1
    {{ }} is a shortcut for the ng-bind directive that can be used without creating an element. As the view is interpolated you may get a fouc when you use {{ }} but you won't when you use ng-bind (because it's an attribute). – Gruff Bunny Jan 15 '14 at 19:36

1 Answers1

0

Ugh, changing value="%% trainer.rating %% to just value="trainer.rating" made it work like a charm

Mark
  • 3,137
  • 4
  • 39
  • 76