I have a Service and a Controller. The controller calls a function, getItems() on the Service. The Service returns an array of data.
However, the controller appears to not be receiving this, oddly enough.
Controller:
ItemModule.controller('ItemController', ['$scope', 'ItemService',
function ($scope, ItemService) {
$scope.items = [];
$scope.getItems = function() {
$scope.items = ItemService.getItems();
}
$scope.getItems();
}
]);
Service:
ItemModule.service('ItemService', ['$rootScope', '$http',
function($rootScope, $http) {
this.getItems = function() {
$http.get($rootScope.root + '/products').success(function(data) {
// This prints it out fine to the console
console.log(data);
return data;
});
}
}
]);
What am I doing wrong?
A quick and dirty fix would be like that:
ItemModule.service('ItemService', ['$rootScope', '$http',
function($rootScope, $http) {
return {
getItems : function(scope) {
$http.get($rootScope.root + '/products').success(function(data) {
scope.items = data;
});
}
}
}
]);
and then in your controller just call:
ItemService.getItems($scope);
But if your controller is a part of route (and probably is) it would be much nicer to use resolve (look here).
Related
amcApp.service('utilService', function ($http, $q,$rootScope) {
var getSupportTypes = function () {
var deferred = $q.defer();
$http.get($rootScope.BaseUrl+'vendor/supportTypes')
.then(function daoSuccess(response) {
console.log("Getting Sub Customer Service call success ", response);
deferred.resolve(response);
}, function daoError(reason) {
console.log("Getting SubC data service call error", reason);
deferred.reject(reason);
});
return deferred.promise;
};
return{
getSupportTypes : getSupportTypes,
};
});
Above is the service I defined.
Below is the controller I defined.
amcApp.controller('contractForm', ['$scope', '$http','$rootScope','$filter', '$uibModal', '$state', 'testService','utilService','contractService',
function ($scope, $http,$rootScope, $filter,$uibModal, testService,utilService,contractService) {
//Service of getting the Support Types.
utilService.getSupportTypes().then(function(response){
$scope.supportTypes = response.data.UtilDataType;
});
}]);
This is the error I'm getting:
Can I get any suggestions?
Check the dependencies what you inject into the controller, you have an extra $state in the array which has not been passed to the function. I would suggest to remove as the following:
amcApp.controller('contractForm', ['$scope', '$http', '$rootScope', '$filter', '$uibModal', 'testService','utilService','contractService',
function ($scope, $http, $rootScope, $filter, $uibModal, testService, utilService, contractService) {
//Service of getting the Support Types.
utilService.getSupportTypes().then(function (response){
$scope.supportTypes = response.data.UtilDataType;
});
}]);
On the other hand I would simply remove all the not used services, I assume this is working also fine:
amcApp.controller('contractForm', ['$scope', 'utilService', function ($scope, utilService) {
//Service of getting the Support Types.
utilService.getSupportTypes().then(function (response) {
$scope.supportTypes = response.data.UtilDataType;
});
}]);
Just a suggestion - if you keep your code clean it is much easier to figure out the root cause of any issues.
The issue is that I can't seem to send information from Controller 1 to Controller 2... I have my service that sets/gets data but it isn't working. The actual error that I'm getting is that Controller 1's dataService.getData is not a function... when it works elsewhere.
Service 1 (in its own file)
app.service('dataService', function() {
var data, queried;
return {
setData: function(queryData) {
this.data = queryData;
this.queried = false;
},
getData: function() {
this.queried = true;
return this.data;
}
};
});
Controller 1 (sending information)
app.controller('MyCtrl', ['$scope', '$location', '$state', function($scope, $location, $state, dataService) {
anotherService.functionName(function(err, data) {
// do some things here
actualService.doesntWork(function(err, data) {
if (!err) {
var query = {};
query.someField = data.someField;
dataService.setData(query);
$state.go("go.somewhere.else");
}
});
});
}]);
Controller 2 (getting information)
app.controller('MyCtrl2', ['$scope', '$location', '$state', function($scope, $location, $state, dataService) {
$scope.buttonPressed = function() {
console.log(dataService.getData());
}
}]);
You didn't injected service dataService inside your MyCtrl & MyCtrl2, ensure dependency should be injected before using it.
Controller
app.controller('MyCtrl', ['$scope', '$location', '$state','dataService', //<-added dependency here
function($scope, $location, $state, dataService) {
anotherService.functionName(function(err, data) {
// do some things here
actualService.doesntWork(function(err, data) {
if (!err) {
var query = {};
query.someField = data.someField;
dataService.setData(query);
$state.go("go.somewhere.else");
}
});
});
}]);
Controller2
app.controller('MyCtrl2', ['$scope', '$location', '$state','dataService',//<-added dependency here
function($scope, $location, $state, dataService) {
$scope.buttonPressed = function() {
console.log(dataService.getData());
}
}]);
I have a controller that starts like this (simplified for this question):
angular.module('myApp.controllers')
.controller('MyController', ['$scope', '$routeParams', 'MyService',
function ($scope, $routeParams, MyService) {
MyService.fetchWithId($routeParams.id).then(function(model) {
$scope.model = model;
});
Which is fine, but then in many places throughout the controller, I have functions that are referred to in the view that refer to the model ...
$scope.someFunctionMyViewNeeds = function() {
return $scope.model.someModelAttribute;
};
Since these often run before the fetch completes, I end up with errors like "cannot read property of undefined" when the view tries to see someModelAttribute.
So far, I've tried three things:
// before the fetch
$scope.model = new Model();
...but I really don't want a new model, and in some cases, cannot complete initialization out of the blue without other dependences.
Another idea is to litter the code with defense against the unready model, like:
return ($scope.model)? $scope.model.someModelAttribute : undefined;
... but that's a lot of defense all over the code for a condition that only exists while the fetch completes.
My third idea has been to "resolve" the model in the route provider, but I don't know how to do that and get at the $routeParams where parameter to fetch the model is kept.
Have I missed a better idea?
Try this if you want to use resolve.
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.when('/things/:id', {
controller: 'ThingsShowController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}/edit">Edit</a>'
});
$routeProvider.when('/things/:id/edit', {
controller: 'ThingsEditController',
resolve: {
model: function ($routeParams, MyService) {
return MyService.fetchWithId(+$routeParams.id);
}
},
template: '<a ng-href="#/things/{{model.id}}">Cancel</a>'
});
});
// Just inject the resolved model into your controllers
app.controller('ThingsShowController', function ($scope, model) {
$scope.model = model;
});
app.controller('ThingsEditController', function ($scope, model) {
$scope.model = model;
});
// The rest is probably irrelevant
app.factory('Model', function () {
function Model(attributes) {
angular.extend(this, attributes);
}
return Model;
});
app.service('MyService', function ($q, Model) {
this.fetchWithId = function (id) {
var deferred = $q.defer();
deferred.resolve(new Model({ id: id }));
return deferred.promise;
};
});
// Just to default where we are
app.run(function ($location) {
$location.path('/things/123');
});
app.run(function ($rootScope, $location) {
$rootScope.$location = $location;
});
// Because $routeParams does not work inside the SO iframe
app.service('$routeParams', function () {this.id = 123;});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.9/angular-route.min.js"></script>
<div ng-app="app">
<div>Route: {{$location.path()}}</div>
<div ng-view=""></div>
</div>
I'm trying to make a basic data pulling using a service and print it on screen when I have data, but something is not working.
My service:
mymodule.factory('MyService', function($http, $q) {
var service = {
getData: function() {
var dfd = $q.defer();
$http.get(apiServerPath).success(function (data) {
dfd.resolve(data);
});
return dfd.promise;
}
}
return service
}
My Controller:
mymodule.controller('myCtrl', ['$scope', 'MyService', function($scope, MyService) {
$scope.myvar = MyService.getData();
}
HTML
<div> {{myvar}} </div>
What I can see from the browser console -
The myvar object turn into a promise object
The success function is being called and 'data' has valid data in it
And for my question and issue - the controller's variable does not change when the defer object is resolving - why?
Promises are no longer auto-unwrapped as of Angular 1.2. In your controller do the following:
mymodule.controller('myCtrl', ['$scope', 'MyService', function($scope, MyService) {
MyService.getData().then(function success(data) {
$scope.myvar = data;
});
}
I have a controller that updates my awards scope:
Controller 1
.controller("awardController", ['$scope', '$rootScope', 'Restangular', "$q", "$location", "TokenRestangular",
function ($scope, $rootScope, Restangular, $q, $location, TokenRestangular) {
$scope.updateAwardScope = function () {
resource = TokenRestangular.all('award');
resource.getList()
.then(function (awards) {
$scope.awards = awards;
})
}
}])
Controller 2
I have another controller 2 with a click event thats outside of this controllers scope. Is it possible for the controller below to call the $scope.updateAwardScope function from controller 1?
.controller('MainController', function ($rootScope, $scope) {
$scope.updateAwardScopeClick = function () {
// somehow call function from controller 1
}
});
I've found the use of the factory/service pattern to be a very effective way of reusing code in angular applications. For this particular case you could create an AwardFactory, inject it in your controllers and then call the update function. i.e
AwardFactory
myApp.factory('AwardFactory', ['TokenRestangular', function(TokenRestangular.all) {
var factory = {
awards: []
};
factory.update = function() {
resource = TokenRestangular.all('award');
resource.getList().then(function (awards) {
factory.awards = awards;
});
return factory.awards; // You can skip the return if you'd like that
};
return factory;
}]);
YourController
.controller('MainController', function ($rootScope, $scope, AwardFactory) {
$scope.updateAwardScopeClick = function () {
AwardFactory.update();
}
});
Hope it helps!
You can use angular broadcast and receive
Controller1
.controller("awardController", ['$scope', '$rootScope', 'Restangular', "$q", "$location", "TokenRestangular",
function ($scope, $rootScope, Restangular, $q, $location, TokenRestangular) {
$scope.updateAwardScope = function () {
resource = TokenRestangular.all('award');
resource.getList()
.then(function (awards) {
$scope.awards = awards;
$rootScope.broadcast("update.awards");
})
}
}])
Controller 2
.controller('MainController', function ($rootScope, $scope) {
$rootScope.$on('update.awards', function(){
$scope.updateAwardScopeClick();
});
$scope.updateAwardScopeClick = function () {
// somehow call function from controller 1
}
});