I have an AngularJS 1.4* application running locally (yet). This app is served by an Laravel 5.1 backend RESTFul API.
I have to make this app that represents a package trip. A package is composed by days, ranging from 0 to N days. Each day have a list of services, ranging from 0 to N services. And a hotel.
My web server, from which my laravel application consumes from, delivers me a pre-setted package, containing a list of days: each one with a list of services and a hotel data (unused so far). On the response I have a list of properties for the package (that don't matter for now) and an array of days, called days_info
. That response is being put in the $scope.package
, on my PackageController
. The PackageController also declares an directive called packageBlock
, that consists in a list of days, and some other data for the package.
<div ng-repeat="day in package.days_info" class='row'>
<div class='col-md-12'>
<package-days-block></package-days-block>
</div>
</div>
Inside <package-days-block>
directive, I have another to iterate through the list of services inside every day.
<div class='container-fluid' ng-repeat='service in day.services' ng-controller="ServiceController">
<service-block></service-block>
</div>
That's where the problem begins: to my undestandment, I now have a $scope.service
inside my ServiceController
. So, I started to change it on my need inside the ServiceController
through a $scope.service
.
The $scope.service has an attribute called service_id
. I put a listener/watcher on it, so at any time the $scope.service.service_id is changed, I ask for another service_table
(holds the informations about the services, it's based on the service_id previously choosen or changed by the user), and put it in the $scope.service.table
.
// ServiceController
$scope.reloadServicesTable = function(service_id, service_day, date, paxes){
MandatoryService.getServiceTable(service_id, service_day, date, paxes)
.then(
function(service_data) {
$scope.service.table = service_data;
},
...
);
The reloadServicesTable
is called on the watcher for the service_id changes.
// ServiceController
$scope.$watch(
'service.service_id', // Places the watcher to watch the changes on the service's ID.
function(new_service, old_service) {
if( new_service === old_service )
return;
$scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);
}
);
The problem starts here: the request for the service's table is called twice when the service_id only changes once.
WHY, GOD, WHY?!
There's another part of my code where I, from the PackageController, run through the entire days_info
array and reads the value of an attribute price
inside the service.table: service.table.price
. In there, I realise that there's two scope's: the one I handling and the other that I have no FREAKING IDEA where it came from!
If I put an console.log($scope);
inside the method that runs through the days_info, I get two scopes for every request. This method is on the PackageController.
Any ideas why this is happening?
P.S.: It's my very first AngularJS application, so, take easy if I messed up on something basic...
EDIT:
As pointed out by an fellow on the comments, my question wasn't very reproducible. Sadly, I can't put here only the part I'm having doubts cause I don't have the slightest idea where the problem lies! (I know that this isn't much of help)
I took some screen shots from the Chrome Console:
First, the requestions fired on the change of the service_id
As you can see, every request is called twice everytime. This is not an one-time-thing. The /api/service/{id}...
is the call for the service's table information. The /api/service/by_route/origin/...
returns an list of services from one city to another (or the same). One does not interfere on the other.
The other image is the output from a console.log from the PackageController $scope, on the time that the service_id is being changed.
As you can see, there's two different scopes. And the b
scope is son of the r
scope. The r
scope is also calling the watcher on the service_id
?
The call for the sums price is been called twice from differente places, as you can see in the image below:
It may solve you issue. Even i had faced exactly the same as you are mentioning.
The reason for me was that, the controller was getting initialized again and there was a separate api call written in that, which was intended to load the page initially.
There can also be a scenario where you have assigned controller twice in the mark up.
<div ng-repeat="day in package.days_info" class='row'>
<div class='col-md-12'>
<package-days-block day="day"></package-days-block>
</div>
</div>
<div class='container-fluid' ng-repeat='service in day.services'>
<service-block service="service"></service-block>
</div>
Pass day
and service
down into directives. Use two way binding to pass your day
and service
changes back up to package.days_info.
Remove your ServiceController
It does not make much sense to ng-repeat a controller. <service-block>
and <package-days-block>
are E directive that handle logic.
Write only one watcher in your PackageController that watch package.days_info
When your day
or service
change, it can simply find out and do something about it.
Just Chill and fix it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With