I have a SocketService (using socket.io) and I make a call to my backend server like so:
SocketService.on("get user data", (response) => {
DataService.data = response;
});
I have a controller like so:
...
.controller("UserController", ($scope, DataService) => {
SocketService.emit("get user data");
$scope.users = DataService.data;
});
Now, this is the flow:
Controller loads, makes a request to our backend using SocketService.
$scope.users becomes equal to an empty array since we didn't get a response yet.
SocketService listens for the response, updates DataService.
The problem is, unless I click the button to load UserController again, I see an empty array. So, first click, I see an empty array. Second click after 1 seconds, I see the users array.
Is there any way to do something like this on Angular?
// pseudo code
SocketService.emit("get user data");
Spinner.show();
SocketService.on("get user data", (response) => {
angular.controllers.resolve("UserController", ($scope) => {
$scope.users = response;
});
Spinner.hide();
});
I don't know your SocketService with socket.io, but if it were a normal angular service and call the backend via $http i would do following:
SocketService (inject $http):
function get(url, config) {
return $http.get(url, config);
};
UserController (inject your SocketService):
function getUserData() {
SocketService.get('myUrl', {})
.then(function(response) {
$scope.users = response.data;
});
}
I hope this give you an impulse to solve your problem.
Related
I'm new to AngularJS and this is my first question in stackoverflow. I've been reading a lot of possible answers for this problem but I didn't find a solution. I have this in my factory (I think the important part is between the dots):
;(() => {
app.factory('Users', users)
users.inject = ['$state', 'UserServices']
function users($state, UserServices) {
users.users = [];
.....
users.activeDeactive = (userId, activate) => {
UserServices.activeDeactive(userId, activate).then(
response => {
console.log(response); //it shows "{status: 0}", which is the desired value
return response;
}
)
}
.....
return users;
}
})()
And this in my controller:
;(() => {
app.controller('UsersCtrl', usersCtrl);
function usersCtrl($scope, $state, Users, users, vendors, profiles, clients) {
Users.users = users;
.....
$scope.activeDeactive = function(userId, activate) {
var response = Users.activeDeactive(userId, activate);
console.log(response); //it shows undefined
}
.....
};
})();
How can I also get "{status: 0}" in the controller? I'm stuck on this for a long time... I've read about waiting for a service to resolve the data, to wait for the promise, etc... but I think this problem is much more simpler, because I've already managed to send the service info to this factory... The problem now is to send the data from the factory to the controller... Thank you very much!
Use below syntax in controller. The reason your code not working is you have written a service called Users.activeDeactive, you are calling it from the controller but not waiting for the response. Its very important to wait for the response. If the service call is successful, it will execute then part. Here you need to catch the response like in given syntax only.
In case of errors, it will go to the error part.
;(() => {
app.controller('UsersCtrl', usersCtrl);
function usersCtrl($scope, $state, Users, users, vendors, profiles, clients) {
Users.users = users;
.....
$scope.activeDeactive = function(userId, activate) {
Users.activeDeactive(userId, activate).then(function(data){
response = data;
console.log(response);
},
function(error){
console.log(error);
});
.....
};
})();
in users factory method return promise.
users.activeDeactive = (userId, activate) => {
return UserServices.activeDeactive(userId, activate).then(
response => {
console.log(response);
return response;
}
)
}
and in controller method change to accept resolve object.
$scope.activeDeactive = function(userId, activate) {
Users.activeDeactive(userId, activate).then(response =>{
console.log(response);
});
}
Reason behind doing is .. UserService looks aync method as you have then in user factory. so controller method will call user factory method and will not wait until userservice returns data as that goes in to event loop. to make it work return promise from user factory method.
I am created an Eshopping Mvc application with webapi and angularjs:
Read and answer:
Application heirarchy for 1 module:
Login => Home=> retailer => retailerlist => product => product list
Application working fine in this scenario:
when inside the Dom , event fires means carry over the data and get into child controller variable.
Home controller event fires ,
var HomeController = function ($scope, $rootScope, $stateParams, $state, LogService,HomeService)
LogService.Login("username", encodeURIComponent("password"))
.then(function (response) {
var SessionData = response.SessionObj;
var DefaultModelObj = { SessionObj: SessionData, add dynamic property};
HomeService.pageLoad(DefaultModelObj)
.then(function (response) {
$rootScope.SessionObj = response.SessionObj
});
}
Service might be like this
var LogService = function ($http, $q) {
this.Login = function (userName, passWord) {
var result = $q.defer();
$http({
method: 'POST',
url: server url
headers: { 'Content-Type': 'application/json' }
})
.success(function (response) {
result.resolve(response);
})
.error(function (response) {
result.reject(response);
});
return result.promise;
}
}
like this home service , other services.
when accesing the response from page event fires get the value and working fine.
ui-sref="home.retailer" ng-click="onSelection(dataItem)"
In state url , it goes and working fine because of getting the data in dataItem and access the values in particular controller .
Note : Everything inside the DOM.
Not working:
consider i am taking one module,
At the point of time , i am in retailer list page , its child of login => home => retailer => retailerlist.
i have do the page refresh or F5,
var RetailerListController = function ($scope, $rootScope, $state, $stateParams, logService, homeService, retailerService, retailerlistservice)
**`var SessionData = $rootScope.CT1SessionObj; // getting undefined happen in browser refresh loss the data.`**
Note: above i have said , Evnt fires takes the values in page navigation working fine.
Steps: for avoiding those i have handle below steps:
In controller Service response depends on
1)call the login service and getting the response some added code from the reponse.
2)pass to Home service and getting the response and some alter and pass to retailer.
3)getting the home response and pass to retailer .
4) getting the retailer response and pass to retailer list .
Note: this working fine .
LogService.Login("username", encodeURIComponent("password"))
.then(function (response) {
var SessionData = response.SessionObj;
var DefaultModelObj = { SessionObj: SessionData, do something};
// another service call
HomeService.pageLoad(DefaultModelObj)
.then(function (response) {
$rootScope.SessionObj = response.SessionObj;
var getresponse= { SessionObj: SessionData, //do some thing added };
// another service call
retailerService.pageLoad( getresponse)
.then(function (response) {
var x = response.SessionObj;
// another service call
retailerListService.pageLoad(x)
.then(function (response) {
$rootScope.SessionObj = response.SessionObj;
}, function (response) {
alert(response.Message)
});
});
});
Note:
My Question is
In every child controller , i have to pass the parent controller response ?
its a better way? or else i have to store the response of each object in local storage to refresh the page issue because of lossing values.
Single object service call contains minimum 100 values:
consider Home service response have 100 values , like that retailer service response and store to local storage is means its a good way and else it will lead to any attack?
Note : IS there any better way:
I am building an app with Ionic and MEAN stack. My express server is running on localhost:3000 while my Ionic public code is running on localhost:8100. From my research, it seems like Ionic can run on a different IP address from the server and should just use ngResource to send $http requests.
So I have a RESTful endpoint like this in server.js
router.get('/', function(req, res){
res.json({"name":"Abdul"});
});
And on the Ionic client code I am sending in a request like this:
app.controller('mainCtrl', function($scope, $resource){
$scope.test = $resource('localhost:3000/');
$scope.test_button = function(){
console.log($scope.test);
}
});
But when I click the test_button, instead of [{"name":"Abdul"}] being logged in the console, I get the following null message:
function Resource(value) {
shallowClearAndCopy(value || {}, this);
}
Can anyone help me out on connecting the client and server?
$resource object will only create an object with having get, save, update, etc. So for calling get method of server, you need to call get method of $resource object. That method will return $promise object will provide a promise. On which you can place .then promise, in which you will get data in success function.
One more thing is, when you are returning data from the server, you are returning object in array format. So in that case you need to specify get method will return array by having isArray: true option there.
$scope.test = $resource('http://localhost:3000/', {}, {get: { isArray: true}});
$scope.test.get().$promise.then(function(data){ //success function
$scope.test = data;
},function(error){ //error function
console.log(error);
})
to make your application more better, you could move up your $resource object to service/factory to make that call reusable.
app.service('dataService', function($resource){
var resourceUrl = $resource('http://localhost:3000/', {}, {get: { isArray: true} });
this.getData = function(){
return resourceUrl.get().$promise;
};
})
Controller
app.controller('mainCtrl', function($scope, dataService){
$scope.test_button = function(){
dataService.getData().then(function(data){ //success function
$scope.test = data;
},function(error){ //error function
console.log(error);
})
}
});
I am learning about the MEAN stack, and have created a REST API which posts a review to a collection in MongoDB.
I have defined a service as given:
angular.module('myApp')
.constant('baseURL', 'http://localhost:8080/');
angular.module('myApp')
.service('addReviews', ['$resource', 'baseURL', function($resource, baseURL) {
this.getReviews = function() {
return $resource(baseURL+'reviews/', null, {'save': {method: 'POST'}});
};
}]);
Now, I am calling this service from my controller:
angular.module('myApp', ['ngResource'])
.controller('reviewController', ['$scope', 'addReviews', function($scope, addReviews) {
$scope.reviewSubmit = function() {
$scope.receivedReviews = false;
var review = {
// some data
};
$scope.reviews = addReviews.getReviews().query(
function(response) {
$scope.reviews = response;
$scope.receivedReviews = true;
},
function(response) {
$scope.reviews = response;
// print error message
}
);
console.log($scope.reviews); // showing empty array
};
}]);
In routes.js, I have configured my route as:
var Reviews = require('./models/reviews');
...
app.post('/reviews', function(req, res) {
Reviews.create(req.body, function(err, post) {
if (err) {
return res.send(err);
}
return res.json(post);
});
});
I am trying to post a new review to the Reviews collection. However, $scope.reviews is showing an empty array. I logged the requests, and it shows a GET request is being to /reviews instead of POST. I think I should use save() instead of query(), but I have seen some tutorials online where they used query() despite the method being PUT/POST in the service. I am really confused. Can anyone point out how I can post the data (in var review) to the Reviews collection?
There are some issues with your code on the angular side of things.
You want to use $resource as an all-purpose object to communicate with the API. It has built-in functionality to:
query: get all resources from a given API endpoint
get: a single resource, usually by specifying that resource's id
save: post, with an object sent across in the body of the request. NOTE: you don't need the {'save': {method: 'POST'}} in your $resource configuration, you get it for free.
remove and delete: self-explanatory
So you'd want to set up your reviews factory (incl. url constant) like:
angular.module('myApp', ['ngResource'])
.constant('baseURL', 'http://localhost:8080/')
.factory('Reviews', ['$resource', 'baseURL', function($resource, baseURL) {
return $resource(baseURL+'reviews/:id', {id: '#id'});
}]);
If you want to have access to all saved reviews in your controller, as $scope.reviews, you'd do something like:
angular.module('myApp')
.controller('reviewController', ['$scope', 'Reviews', function($scope, Reviews) {
// hit API endpoint to get all reviews
// will have to have app.get('/reviews', function(req, res) {...})
// configured in your node code
Reviews.query(function(data) {
$scope.reviews = data;
}, function(error) {
console.log(error);
});
// and if you want to take a user-written review, say $scope.userReview,
// from the view and save it to the database on click function submitReview()...
$scope.userReview = {
message: '',
createdTime: null
};
// ^ not sure what your ReviewSchema looks like on the backend, but for example...
$scope.submitReview = function() {
if ($scope.userReview.message.length) {
$scope.userReview.createdTime = Date.now();
Reviews.save($scope.userReview);
// ^ this will make POST request with the $scope.userReview object as the request body
}
};
}]);
The create method on your back end looks fine. The object (or maybe just string) you send across will have to match your review schema. You may want to log the request body to make sure you're getting what you expect.
Have a look at this short post on using $resource to interact with RESTful APIs, and (the slightly more confusing) angular $resource docs, for more information on the $resource service.
Hope this helps you!
i have written a service with take parameter on the basis of which it response me with the response of http request.
this.getPaymentDueDetails=function(date){
this.getfromRemote('paymentdue/'+btoa(date))
.success(function(response){
return response;
})
.error(function(response){
return false;
})
}
getfromRemote is my another service which make http request
now i am trying to get the response of this service call inside my controller function
$scope.callDueReports=function(blockNum){
var data;
data=myAngService.getPaymentDueDetails('2015-04-20');
console.log(data);
}
its quite obvious that i wont get any thing in data as the page loads initially but i want the result of getPaymentDueDetails int it.
Please modify your service to return the promise like below.
this.getPaymentDueDetails = function(date) {
return this.getfromRemote('paymentdue/' + btoa(date));
};
And in controller check if the promise is resolved.
$scope.callDueReports = function(blockNum) {
var data;
myAngService.getPaymentDueDetails('2015-04-20').then(function(dataFromService) {
data = dataFromService;
console.log(data);
})
.catch(function(response) {
console.error('error');
});
};