Reputation: 11
I am currently using Angular 1.3.14 and I would like to make an request using $http whenever a link is clicked. I am trying to place the $http request in a service so it's not bound to any one controller and can be accessed by multiple controllers. I've created two functions sayHello() and getData(). I want each one to console.log when clicked. Only the sayHello() function does, but not the getData() function.. Here's what I don't understand.
Why does the $http request fire on load, and not on click whereas the sayHello function works perfectly?
How can I modify my code so it works as intended?
<p><a href="#" ng-click="getData()">Console Log Our Data</a></p>
<p>
<a href="#" ng-click="sayHello()">Console Log The Word "Hello"</a></p>
var app = angular.module('myApp', [])
.controller('mainCtrl', function($scope, dataService){
$scope.sayHello = dataService.sayHello;
$scope.getData = dataService.getData(function(response){
$scope.myData = response.data;
console.log($scope.myData);
});
})
.service('dataService', function($http){
this.getData = function(callback){
$http.get('http://jsonplaceholder.typicode.com/posts')
.then(callback);
}
this.sayHello = function(){
console.log("Hello!");
}
});
Codepen for reference http://codepen.io/benweiser/pen/remvvo/
Upvotes: 1
Views: 180
Reputation: 4876
That's because $scope.getData
is equal to undefined when it should be a function
$scope.getData = function () {
dataService.getData(function(response) {
$scope.myData = response.data
console.log($scope.myData)
})
}
Update: You can send parameters either from the call to the method or from the method itself, suppose you have the following input
<input ng-model="name">
Then you can use the send the value and use it in your service as follows
<a ng-click="getData(name)">get data</a>
$scope.getData = function (name) {
dataService.getData(name)
.then(function (response) { ... })
}
Or using it directly in the controller
<a ng-click="getData()">get data</a>
$scope.getData = function () {
dataService.getData($scope.name)
.then(function (response) { ... })
}
Note that both assume that dataService.getData()
returns a promise instead of passing the callback so you'd also need to do the following on your service if you want to code it like above
this.getData = function (name) {
// do something with name
return $http.get('http://jsonplaceholder.typicode.com/posts/' + name)
}
You should read more on Promises vs callbacks and how you can take advantage of them :)
Upvotes: 2
Reputation: 31
The Ajax query was being made when controller was first loading. Your bind with "getData" wasn't with a function, but with an ajax call, and that was why it was not triggered.
This refactor works on codepen:
'use strict';
var app = angular.module('myApp', [])
.controller('mainCtrl', function($scope, dataService){
$scope.sayHello = dataService.sayHello;
$scope.getData = function(){
dataService.getData().then(
function(response){
$scope.myData = response.data;
console.log($scope.myData);
}
);
}
})
.service('dataService', function($http){
this.getData = function(callback){
return $http.get('http://jsonplaceholder.typicode.com/posts');
}
this.sayHello = function(){
console.log("Hello!");
}
});
Main updates:
Upvotes: 0
Reputation: 6939
When you do this
$scope.getData = dataService.getData(function(response){
$scope.myData = response.data;
console.log($scope.myData);
});
})
dataService.getData get executed immediately. As a result, $scope.getData is set to a promise instead of a function you intent to bind to ng-click
change this line $scope.getData = dataService.getData to the following which will actually set a function with callback to $scope.getData
$scope.getData = dataService.getData.bind(this, function(response) {
$scope.myData = response.data;
console.log($scope.myData);
});
Upvotes: 1
Reputation: 5606
I would try doing something like this. Should be easy to apply to your code above
//in your factory
app.factory('dataFactory',function($http){
factory = {};
//get data
factory.getData = function(obj){
return $http({
method: 'GET',
url: 'http://jsonplaceholder.typicode.com/postsn'
})
};
return factory
});
//in your controller
app.controller(someCtrl,function($scope,dataFactory){
dataFactory.getData().then(function(data){
console.log('This will be your data: ', data)
})
})
Upvotes: 0