Reputation: 2231
I have this code in my service
orderSewaService.vehicleDetail = function (license_plate) {
//var defer = $q.defer();
var config = {
headers: {
'X-Parse-Application-Id': parseAppId
},
params: {
where: {
vehicle_license_plate: license_plate,
vehicle_status: 'available'
},
limit: 1,
include: 'car_id.car_class_id,pool_id.city_id,partner_id.user_id'
}
}
return $http.get('http://128.199.249.233:1337/parse/classes/vehicle', config).then(function (response) {
var detail = {
license_plate: response.data.results[0].vehicle_license_plate,
photo: response.data.results[0].vehicle_photo,
partner_name: response.data.results[0].partner_id.user_id.full_name,
year: response.data.results[0].vehicle_year,
class: response.data.results[0].car_id.car_class_id.name,
pool_address: response.data.results[0].pool_id.pool_address,
city: response.data.results[0].pool_id.city_id.city_name,
zone_id: response.data.results[0].zone_id.objectId,
car_class_id: response.data.results[0].car_id.car_class_id.objectId
};
return detail;
//defer.resolve(detail);
}, function (error) {
//defer.reject(error);
return error;
});
//return defer.promise;
};
in my controller
$scope.vehicle = {};
orderSewaService.vehicleDetail($routeParams.license_plate).then(function(response){
$scope.vehicle = response;//rendered in view
console.log($scope.vehicle); //log object success
}, function (error) {
console.log(error);
});
console.log($scope.vehicle); //doesn't work //empty object
//My goal is I will call other service function like this
orderSewaService.infoTarif($scope.vehicle.zone_id, $scope.vehicle.car_class_id).then(...);
Already read this access scope data from outside function but looks like to complex or not suit for my simple goal.
How I can access $scope.vehicle
outside function or how to achieve my goal ?
And I don't think $rootScope
is good solution in this case.
Upvotes: 0
Views: 109
Reputation: 5918
I think there are two matter of concerns in this question.
Firstly - sync & async methods
Since orderSewaService.vehicleDetail
is asynchronous, $scope.vehicle
would be null.
If you are not sure what that means, compare the two:
var foo = null;
foo = ['a','b'];
console.log(foo); // ['a','b']
versus
var foo = null;
setTimeout(function(){
foo = ['a','b'];
console.log(foo); // array
}, 500); // or any value including zero
console.log(foo); // null
Conclusively, your code should look like this:
$scope.vehicle = {};
orderSewaService
.vehicleDetail($routeParams.license_plate)
.then(function(response){
$scope.vehicle = response;//rendered in view
console.log($scope.vehicle); //log object success
//My goal is I will call other service function like this
orderSewaService.infoTarif($scope.vehicle.zone_id, $scope.vehicle.car_class_id).then(...);
}, function (error) {
console.log(error);
});
There are a ton of articles and docs that describe this, if you are further interested.
Secondly - load contents before reaching controller
Now, from how you described the problem, it seems like you also want to load the contents of orderSewaService.vehicleDetail
based on a URL parameter before it reaches the controller. Otherwise, you will have to call orderSewaService.vehicleDetail
and orderSewaService.infoTarif
in every controller.
A much cleaner and more common approach is to use ui-router
's $stateProvider
. Tutorials here
If you run a few examples from their docs, you can inject dependencies into your controller like this:
app.route.js
$stateProvider
.state('vehicles', {
url: '/vehicles',
resolve: {
vehicles: ['VehiclesService', function(VehiclesService){
return VehiclesService.getAll();
}]
},
controller: 'VehiclesListCtrl',
templateUrl: 'vehicles.html'
})
.state('vehicles.detail', {
url: '/vehicles/:vehicleId',
resolve: {
info: ['VehiclesService', '$stateParams', function(VehiclesService, $stateParams){
return VehiclesService.get($stateParams.vehicleId)
.then(function(vehicle){
return orderSewaService.infoTarif(vehicle.zone_id, vehicle.car_class_id)
.then(function(tarif){
return {
vehicle: vehicle,
tarif: tarif
};
});
});
}]
},
controller: 'VehicleDetailCtrl',
templateUrl: 'vehicle.detail.html'
});
vehicle.detail.controller.js
.controller('VehicleDetailCtrl', VehicleDetailCtrl);
VehicleDetailCtrl.$inject = [
'$scope',
'info'
];
function VehicleDetailCtrl(
$scope,
info
) {
console.log('vehicle %o tarif %o', info.vehicle, info.tarif);
}
vehicles.controller.js
.controller('VehiclesCtrl', VehiclesCtrl);
VehiclesCtrl.$inject = [
'$scope',
'vehicles'
];
function VehiclesCtrl(
$scope,
vehicles
) {
console.log('vehicles list %o', vehicles);
}
To access this state, you need to do something like
menu.html
<a ui-sref="vehicles.detail({vehicleId: 1234})">
I purposely did not make vehicles
route abstract for illustration purposes. You may want to look into that if you want to create nested state/views.
I hope this helps.
Upvotes: 0
Reputation: 909
The problem is with the way this controller code flow works.
$scope.vehicle = {}; //vehicle property is declared and defined as empty obj in the $scope
orderSewaService.vehicleDetail($routeParams.license_plate)
This is an ajax call, js calls this method and then goes to the next line , after the end of this method, i.e.
console.log($scope.vehicle);
without waiting for the call to return and populate $scope.vehicle with your response.
So, try this:
`
$scope.vehicle = {};
orderSewaService.vehicleDetail($routeParams.license_plate).then(function(response){
$scope.vehicle = response;//rendered in view
getInfoTarif();
}, function (error) {
console.log(error);
});
function getInfoTarif(){
console.log($scope.vehicle);
orderSewaService.infoTarif($scope.vehicle.zone_id,$scope.vehicle.car_class_id).then(...);
}
`
Upvotes: 0
Reputation: 222522
You need to declare $scope.vehicle outside the function call,
somewhere in your controller at the begining,
If it's an array
$scope.vehicle =[];
Upvotes: 2