I am facing issue while displaying data in table.
I am using a customservice to fetch data from a json file and then inserting that data into $rootScope of an object.
But when I run the view,it comes blank with no errors.In the view,i am using below line of code in the view to iterate the array of objects "books"
Please guide me.
controller.js
Controllers.controller('BookListCtrl_Student', ['$scope','$rootScope','$http','$location','BookData',
function ($scope, $rootScope, $http, $location, BookData) {
$rootScope.books=[];
$rootScope.books.push(BookData.getData());
$scope.bookLists = ['All Books', 'Available Books'];
$scope.selection = $scope.bookLists[0];
$scope.backToLogin = function() {
$location.path("/main");
}
}
]);
customservice.js
Controllers.factory('BookData',['$http',function(http){
return {
getData: function() {
return http.get('data/books.json').then(function(result){
return result.data;
});
}
};
}
]);
The problem is when you do $rootScope.books.push(BookData.getData()) it calls your getData(), but it never executes the promise. To fix it you would need to handle the promise within the controller and assign the data then.
customservice.js
return http.get('data/books.json');
controller.js
BookData.getData().then(function(resp){
$rootScope.books.push(resp.data);
})
Heres a plunker with a quick example - https://plnkr.co/edit/ivdLd9wilmWW8oUnrMsh?p=preview
Related
I'm having 2 controller placed on a same page and using a same factory. All things i want is when a function in controller 1 execute, it will call to the function inside factory then the $scope in controller 2 will be update its value. When page is loaded controller can get the list but after controller 1 call the factory, nothing was changed, no any call to server...
Here is Controller 1:
app.controller('controller1', function ($scope, $http, globalServices) {
$scope.createFuntion = function(){
$http.post(url, $.param(some_object)).then(function(response){
//Handle something ...
globalServices.userList();
});
}});
Here is Controller 2:
app.controller('controller2', function ($scope, $http, globalServices) {
$scope.users = globleServices.userList();});
Here is factory:
app.factory('globalServices', function ($http) {
return{
userList: function(){
var users_data = [];
$http.get(url).then(function (response) {
var res = response.data;
if (res.status === 200) {
angular.forEach(res.data, function (staff) {
users_data.push(staff);
});
} else {
alert('Oops! Somethings went wrong!');
}
});
return users_data;
}
}});
There is a thing in the AngularJs space and JavaScript in general referred to as the dot rule. If you have a property on an object like
service.data
when you assign that to another object
$scope.data = service.data;
It assigns a reference to the object and now if you update the service the controller does not know about the new data.
Using the dot rule you can have an object on the service that holds data objects
service.data = {};
this object should never change reference to a new object and always be the same instance and you can add new properties to it
service.data.userList = response.userList;
Now if you assign the data in the service to the scope
$scope.data = service.data;
and in the template use
<div ng-repeat="user in data.userList">{{ user.name }}</div>
Userlist will be updated when the service updates the userList.
You should never inject $http into controllers, you should only inject services into controllers and have services make http calls. Injecting $scope is an outdated method of doing AngularJs, you are following outdated tutorials and should look into using the controllerAs syntax or use components that wrap the controllerAs syntax with an Angular 2 style of development.
Create an object in your factory that will somehow serve as a state then create a getter for it. Separate your fetch function and getUserList. See the modified code below.
app.factory('globalServices', function ($http) {
var list = {
users_data: []
}
return{
getUserList: getUserList,
fetchUserList: fetchUserList
}
function getUserList() {
return list;
}
function fetchUserList() {
list.users_data = [];
$http.get(url).then(function (response) {
var res = response.data;
if (res.status === 200) {
angular.forEach(res.data, function (staff) {
list.users_data.push(staff);
});
} else {
alert('Oops! Somethings went wrong!');
}
});
}
});
Now in your controller1
app.controller('controller1', function ($scope, $http, globalServices) {
$scope.createFuntion = function(){
$http.post(url, $.param(some_object)).then(function(response){
//Handle something ...
globalServices.fetchUserList();
});
}});
and in your controller2
app.controller('controller2', function ($scope, $http, globalServices) {
$scope.users = globalServices.getUserList();
});
Now your $scope.users listen to every change in your user_data.
Access the array thru $scope.users.users_data
Trying to return JSON data is causing a error in my service. Here is the code...looks simple enough!
var app = angular.module('easyjet', []);
app.service('FlightsService', function($http) {
return {
'selectedResult': null,
'resultsData': $http.get('http://ejtestbed.herokuapp.com/flights')
};
});
app.controller('ResultsController', function($scope, FlightsService) {
// Default sort setting
$scope.order = "flightNumber.number";
// Using service
$scope.flights = FlightsService;
});
app.controller('DetailedFlightController', function($scope, FlightsService) {
// Using service
$scope.flights = FlightsService;
});
How can I fix this? Thanks in advance
Your resultsData property needs to return a function, not an $http request:
Working example: https://jsfiddle.net/yh26oey6/
return {
'selectedResult': null,
'resultsData': function() {
return $http.get('https://api.zippopotam.us/us/90210');
}
And, without seeing how you're calling the service, there could be other issues also.
I know this question has been answered but given solutions didn't work for me. Everything looks okey, but the contento between curly brackets it's not showing on screen.
<div ng-controller="Hello">
<p>The ID is {{greeting.ip}}</p>
<p>The content is {{greeting.ip}}</p>
</div>
The controller is the folling:
'use strict';
angular.module('sbAdminApp')
.controller('Hello',['$scope','$http', function ($scope, $http) {
$http.get('http://ip.jsontest.com/')
.then(function (data) {
$scope.greeting = data;
console.log($scope.greeting);
});
}]);
And in my app.js, im declaring this:
.state('dashboard.test', {
templateUrl: 'views/test.html',
url: '/test',
controller: 'Hello',
resolve: {
loadMyFiles: function ($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'sbAdminApp',
files: ['scripts/controllers/helloWorld.js']
})
}
}
})
The JSON URL from where I'm getting the data is this.
And here are the pics with the output from the console:
$scope.greeting = data; This line is wrong.
It should be $scope.greeting = data.data;
EDIT:
Because you are assigning your response from the server to that variable and you need only the data returned from the API call. You response object contains stuff like headers and status code and the data property which actually contains your the data you need like id and stuff. If you want to get the id from your response object you can do it like this: greeting.data.id.
I always name my response variable res or response so not to mess it up. Like this:
$http.get('http://ip.jsontest.com/')
.then(function (res) {
$scope.greeting = res.data;
console.log($scope.greeting);
});
}]);
The problem is you're doing the following:
$scope.greeting = data;
But according to your JSON it should be:
$scope.greeting = data.data;
The data variable holds the whole JSON object, and you want the data key from it.
So this is my service that I use to fetch user details.
angular.module('app')
.factory('userDetailService', function($http) {
var userData = {};
function getUserDetails(userId) {
if (userId) {
return $http.get("/users/" + userId).success(function(data) {
angular.copy(data[0], userData);
});
}
}
return {
userData: userData,
getUserDetails: getUserDetails
}
})
Now in Controller 1 that uses this service, I have this bit of code which works fine as I get the relevant data.
$scope.getUserId = function(userId) {
if (userId) {
$scope.userData = userDetailService.userData;
userDetailService.getUserDetails(userId).success(function() {
console.log($scope.userData); //Prints valid user data
});
}
};
After this function executes in Controller 1, I try to do the following in Controller 2:
$scope.userData = userDetailService.userData;
console.log($scope.userData); //Prints null
But $scope.userData is null. Isn't the whole purpose of using a service to share data between controllers? Since I have already set the value of userData in Controller 1, shouldn't I be able to access it in Controller 2?
Weirdly enough, the modal dialog which is the template for Controller 2 is able to access data in the form of {{userData.first_name}} or {{userData.last_name}}. If this works, why is $scope.userData null? What am I missing?
Edit:
Template 1:
<div id="myModal" ng-controller="Controller 1">
<modal-configure-user></modal-configure-user>
<a data-toggle="modal" data-target="#configureUserModal" href="#" ng-click="getUserId(user.id)" data-id="user.id">{{user.first_name + ' ' +user.last_name}}</a>
</div>
Template 2:
<div ng-controller="Controller 2" id="configureUserModal">
</div>
Both are modal dialog windows.
Your approach is not very reliable, since you can't be 100% sure that data has already loaded when you try to access it in the second controller. Instead of assigning user data to variable always invoke getUserDetails method, which returns a promise. Then you just need to cache loaded data to avoid duplicated requests.
angular.module('app')
.factory('userDetailService', function($q, $http) {
var userData;
function getUserDetails(userId) {
if (userId) {
return userData ? $q.when(userData) : $http.get("/users/" + userId).success(function(data) {
userData = data;
return userData;
});
}
}
return {
getUserDetails: getUserDetails
}
});
Wrapping userData into $q.when creates a promise object, which resolves immediately. This is what you need, because service API is now consistent - you always deal with promises.
The usage in both controller then would be:
userDetailService.getUserDetails(userId).then(function(data) {
$scope.userData = data;
});
i am having a problem accessing the $scope. as it seems it is not working for me.
i have a resource:
squashApp.factory('CourtsService', function($resource) {
return $resource('/api/court/:num', {num: '#num'});
});
and my controller does:
squashApp.controller('CourtsController',
function CourtsController($scope, $window, $http, CourtsService) {
CourtsService.get({num:1}, function(data){
$scope.courts = data;
})
});
my server succeeds in returing a data which is in format of javascript object (JSON).
i have checked it. but for some reason the $scope is not updated and after this callback my view is not changing at all.
help please
I created a demo for you and your code looks ok.
However, it is always good to add some logic for the callback when the error occurs like this, so your app will not die silently.
squashApp.controller('CourtsController', function CourtsController($scope, $window, $http, CourtsService) {
CourtsService.get({
num: 1
}, function (data) {
console.log('success');
$scope.courts = data;
}, function (data) { // -> error handling
console.log('failed');
$scope.courts = data;
})
});
Demo
A simple way to access your $scope using angular $resource by using $promise (recommended)
squashApp.controller('CourtsController',
function CourtsController($scope,CourtsService) {
CourtsService.get({num:1}).$promise.then(function(data){
//$scope -- can be accessed here
}, function(failed){
}
});