Angularjs data binding between controller and service - angularjs

I'm not able to get the data binding between controller and service working.
I have a controller and a factory which makes an HTTP call. I would like to be able to call the factory method from other services and see the controller attributes get updated. I tried different options but none of them seem to be working. Any ideas would be greatly appreciated.
Please see the code here:
http://plnkr.co/edit/d3c16z?p=preview
Here is the javascript code.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.controller('EventDetailCtrl', ['$http', 'EventDetailSvc', '$scope',
function ($http, EventDetailSvc, $scope) {
this.event = EventDetailSvc.event;
EventDetailSvc.getEvent();
console.log(self.event);
$scope.$watch(angular.bind(this, function () {
console.log('under watch');
console.log(this.event);
return this.event;
}), function (newVal, oldVal) {
console.log('under watch2');
console.log(newVal);
this.event = newVal;
});
}])
.factory('EventDetailSvc', ['$http', function ($http) {
var event = {};
var factory = {};
factory.getEvent = function() {
$http.get('http://ip.jsontest.com')
.then(function (response) {
this.event = response.data;
console.log('http successful');
console.log(this.event);
return this.event;
}, function (errResponse) {
console.error("error while retrieving event");
})
};
factory.event = event;
return factory;
}]);

It seems to me that you have nested the event object inside of a factory object. You should be returning event directly instead wrapping it with factory. As it stands now you would need to call EventDetailSvc.factory.event to access your object.

Related

writing a simple Angular Service

OK, I've built services before but obviously I don't actually know what makes them tick, since I can't seem to debug this ultra-simple service call:
app.js:
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope, dataService) {
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
dataService.js:
(function() {
'use strict';
angular
.module('gridApp')
.service('dataService', dataService)
dataService.$inject = [];
function dataService() {
console.log("I am the dataService and I am loaded");
var foo = 1;
function getData () {
return 2;
}
}
})();
I see this on-screen: I am Angular and I am working. so Angular is loading.
I see this in console: I am the dataService and I am loaded so the dataService is actually being loaded.
But then the console.log is:
undefined (line 8)
TypeError: dataService.getData is not a function (line 9)
What am I missing?
The previous answers are correct in that your $http injection was wrong, but you are also not attaching your service functions to the service:
function dataService() {
var dataService = this; //get a reference to the service
//attach your functions and variables to the service reference
dataService.foo = 1;
dataService.getData = function() {
return 2;
};
}
An Angular service is very simply an object class. It is also a singleton, meaning it's instantiated only once per run of your app. When the service is instantiated it is very much akin to calling the new operator on your dataService "class":
var $dataService = new dataService();
So, when you inject dataService into your controller, you are actually getting an instance, $dataService, of your dataService "class".
See this blog entry for further reading: https://tylermcginnis.com/angularjs-factory-vs-service-vs-provider-5f426cfe6b8c#.sneoo52nk
You are missing the 2nd parameter $http in the function. The named parameters and the actual parameters in function need to be the same, same order and same number. What happened before is that dataService was being assigned an $http instance and the actual dataService was not injected at all because there was no 3rd parameter to inject it into.
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope, $http, dataService) {
// ----was missing-----^
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
We have missed the second param '$http' in function. Just add the '$http' param, it should work fine
var gridApp = angular.module('gridApp', []);
gridApp.controller('mainController', ['$scope', '$http', 'dataService',
function($scope,$http, dataService) {
$scope.message = 'I am Angular and I am working.';
var init = function(){
console.log(dataService.foo);
console.log(dataService.getData());
};
init();
}]);
This is how I've been taught to set up services:
function dataService() {
var dataService = {};
var _foo = 1;
var _getData = function () { return 2; }
dataService.foo = _foo;
dataService.getData = _getData;
return dataService;
}
I believe this facilitates public/private methods/vars.
For reference, this is the full code accessing my service:
app.js:
var gridApp = angular.module('gridApp', []);
// create the controller and inject Angular's $scope
gridApp.controller('mainController', ['$scope', 'dataService', function($scope, dataService) {
// create a message to display in our view
$scope.message = 'Angular is working';
var init = function(){
getPackageData();
};
var getPackageData = function (){
return dataService.getData().then(
function successCallback(response) {
console.log(response);
},
function errorCallback(response) {
console.log(response);
}
);
};
init();
}]);
dataService.js:
(function() {
'use strict';
angular
.module('gridApp')
.service('dataService', dataService)
dataService.$inject = ['$http'];
function dataService($http) {
var dataService = {};
var _getData = function () {
return $http({
method: 'GET',
url: 'data/packages.json'
})
.then(function successCallback(response) {
return response;
},
function errorCallback(response) {
return response;
});
}
dataService.getData = _getData;
return dataService;
}
})();

View not updating when using $controller service in angular

I have two controllers. The view is tied to the firstCtrl. I'm trying to run the function in the second one so the view is updated. Function runs but view not updated. Any ideas?
<div>{{people.length}}</div>
angular.module('myApp').controller('firstCtrl', function($scope, $http) {
var self = this;
$scope.people = [];
function getData() {
$http.get('/people').then(function(res) {
$scope.people = res.data;
});
}
getData();
$scope.getData = getData;
self.getData = function(){
$scope.getData();
};
return self;
});
angular.module('myApp').controller('secondCtrl', function( $controller, $scope, $http) {
var firstCtrl= $controller('firstCtrl', { $scope: $scope.$new() });
firstCtrl.getData(); //This runs but view is not updated above.
});
I think your code has some problem with the $scope. So instead of pass data directly in the firstCtrl. I pass a callback to getData function and assign data to $scope.people in the callback.
Here is the working Plunker:
> http://plnkr.co/edit/QznxFL

How can I passing Parameter angularjs factory $http and $stateParameters

App.factory('menuService', function ($http) {
var urlBase = 'Services/MenuService.asmx/GetAllMenu';
var factory = {};
factory.getAllMenus= function () {
return $http.get(urlBase);
};
return factory;
});
Controller:
App.controller("sampleController", function ($scope, menuService) {
$scope.List = [];
var menuData=function(data, status){
$scope.List = data;
console.log($scope.List);
}
menuService.getAllMenus().success(menuData);
});
/// Working perfect...
How can i use same service by other controller?
I've tried this one but wrong...
App.controller("viewDetailMenu", function ($scope, menuService, $stateParams) {
$scope.menu = menuService.getMenu($stateParams.id);
});
Here I share image how it look..
Please help me!...
You need to have all functions/methods defined if you want to use them. You getMenu function/method is not defined so it will generate an error. Please look at below code. You can add number of functions. You factory is share by all controllers so you can use it in any controller.
App.factory('menuService', function ($http) {
var urlBase = 'Services/MenuService.asmx/GetAllMenu';
var factory = {};
factory.getAllMenus= function () {
return $http.get(urlBase);
},
factory.getMenu=function(id){
return $http.get(urlBase +"/ID="+ id) // write it according to your API.
}
return factory;
});
And then,
App.controller("viewDetailMenu", function ($scope, menuService, $stateParams) {
$scope.menu = menuService.getMenu($stateParams.id).success(function(data,status){
}).error(function(data,status){
});
});

Angularjs cannot get data from service

I'm trying to pass data from one controller to another using a service, however no matter what I'm trying it always returns 'undefined' on the second controller. Here is my service :
app.service('myService', ['$rootScope', '$http', function ($rootScope, $http) {
var savedData = {}
this.setData = function (data) {
savedData = data;
console.log('Data saved !', savedData);
}
this.getData = function get() {
console.log('Data used !', savedData);
return this.savedData;
}
}]);
Here is controller1 :
.controller('HomeCtrl', ['$scope','$location','$firebaseSimpleLogin','myService','$cookies','$window', function($scope,$location, $firebaseSimpleLogin, myService, $cookies, $window) {
loginObj.$login('password', {
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
myService.setData(user);
console.log('myservice:', myService.getData()); // works fine
}]);
And then controller2:
// Dashboard controller
.controller('DashboardCtrl', ['$scope','$firebaseSimpleLogin','myService',function($scope,$firebaseSimpleLogin, $location, myService) {
console.log('myservice:', myService.getData()); //returns undefined
}]);
That is simple code, unfortunately I've been struggling for a few hours now, any suggestion ? Thanks.
Created a fiddle here:
http://jsfiddle.net/frishi/8yn3nhfw/16
To isolate the problem, can you remove the dependencies from the definition for myService and see if that makes it work? Look at the console after you load the fiddle.
var app = angular.module('app', [])
.service('myService', function(){
this.getData = function(){
return "got Data";
}
})
I assume the issue is that you are returning this.savedData in the service. Try returning savedData.
this behaves different in Javascript than in other languages.

Problems using $http inside a Service

I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
});
}]);
Controller:
angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {
console.log(FormService.dropdownData); // Shows full object incl industries
console.log(FormService.dropdownData.industries); // empty object {}
}]);
How do I get FormService.dropdownData.industries in my controller?
Create a service like below
appService.factory('Service', function ($http) {
return {
getIndustries: function () {
return $http.get('/json').then(function (response) {
return response.data;
});
}
}
});
Call in controller
appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
$scope.Industries = Service.getIndustries();
}]);
Hope this will help
Add a method to your service and use $Http.get inside that like below
_this.getindustries = function (callback) {
return $http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
callback(_this.dropdownData)
});
};
In your controller need to access it like below.
angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
FormService.getDropdownData(function (dropdownData) {
console.log(dropdownData); // Shows full object incl industries
console.log(dropdownData.industries); // object {}
});
} ]);
Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
//note that this is resp.data.industries, NOT resp.industries
_this.dropdownData.industries = resp.data.industries;
});
}]);
Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions
Returning a promise
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries = $http.get('/json');
}]);
//Controller
FormService.industries
.then(function(res){
$scope.industries = res.industries
});
Resolving with routeProvider / ui-route
See: $http request before AngularJS app initialises?
You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.
The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.
It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
// when the ansyc call returns, populate the object,
// but preserve the reference
angular.copy( resp.data.industries, _this.dropdownData.industries);
return _this.dropdownData.industries;
});
}]);
Controller
app.controller('ctrl', function($scope, FormService){
// you can bind this to the view, even though the $http call has not returned yet
// the view will update automatically since the reference was preserved
$scope.dropdownData = FormService.dropdownData;
// alternatively, you can hook into the $http call back through the $promise
FormService.dropdownData.industries.$promise.success(function(industries) {
console.log(industries);
});
});

Resources