I have a factory:
myService:
'use strict';
app.factory('myService', ['$resource', 'ngAuthSettings', function ($resource, ngAuthSettings) {
var serviceBase = ngAuthSettings.apiServiceBaseUri;
return $resource(serviceBase + 'api/category/', {}, {
update: {
method: 'PUT'
},
getAllByCategory: {
url: serviceBase + 'api/category/GetAllByCategory',
method: 'GET', isArray: true
}
});
}]);
Then I have a controller:
searchController:
'use strict';
app.controller('searchController',
['ngAuthSettings', '$scope', 'myService', '$routeParams', '$location',
function (ngAuthSettings, $scope, myService, $routeParams, $location) {
function init() {
var search = $location.search();
var keywords = search.keywords;
var model = myService.getAllByCategory({ categoryId: 2, page: $routeParams.page });
$scope.categoryAds = model.ads;
$scope.bigTotalItems = model.totalCount;
$scope.maxSize = ngAuthSettings.maxPagingSize;
}
init();
}]);
Why my model.ads is always undefined? Isn't this the right way to call $resource custom method in controller?
As response may take some time but you are adding assignment very immediatly hence it happening put it in promise/action after resource,
'use strict';
app.controller('searchController', ['ngAuthSettings', '$scope', 'myService', '$routeParams', '$location',
function (ngAuthSettings, $scope, myService, $routeParams, $location) {
function init() {
var search = $location.search();
var keywords = search.keywords;
var model = myService.getAllByCategory({ categoryId: 2, page: $routeParams.page },
function() {
$scope.categoryAds = model.ads;
$scope.bigTotalItems = model.totalCount;
$scope.maxSize = ngAuthSettings.maxPagingSize;
}
);
}
init();
}
]);
Related
I want to wait for an http response before exiting angular controller. I have written the following code. But id doesn't work as the controller still exits before the http call is returned. Can anyone help me out to fix this? Thanks in advance.
var app = angular.module('app', []);
app.factory('MyService', function ($http) {
return $http.get('/api/endpoint').then(function(res){
return res.data;
});
});
app.controller('MyController', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
MyService.then(function(data){
$scope.myVarialbe = data;
})
}]);
I would write this as below.
'use strict';
(function () {
function MyService($http) {
function getService() {
var url = yourURL;
return $http({ method: 'GET', cache: false, url: url });
}
return {
getService: getService
};
}
angular.module('app')
.factory('MyService', MyService);
}());
controller code:
MyService.getService().then(function(response) {
});
You can use like this factory just return request response promise and in controller use .then on returned promise.
var app = angular.module('app', []);
app.factory('MyService', ['$http',function($http) {
return {
getData: function() {
return $http.get('/api/endpoint');
}
};
}]);
app.controller('MyController', ['$scope', '$http', 'MyService', function($scope, $http, MyService){
MyService.getData().then(function(response){
$scope.myVarialbe = response.data;
});
}]);
Use $q is better.
Eg:
app.factory('MyService', ['$http', '$q', function($http, $q) {
return {
getData: function() {
var deferred = $q.defer();
$http.get('/api/endpoint')
.then( function(resp) {
deferred.resolve( resp.data );
});
return deferred.promise;
}
};
}]);
app.controller('MyController', ['$scope', 'MyService',function($scope, MyService){
MyService.getData().then(function(data){
$scope.myVarialbe = data;
})
}]);
I have two controllers. I want to update a variable from one controller to another controller using service but its not updating.
I want the variable $scope.names in controller 'select' to update in the controller 'current' and display it
app.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$http.get('/myapp/stocknames').
success(function(data) {
$scope.names=data;
myService.names=data;
});
}]);
I am using myService to exchange the data between the two controllers. I have declared in my service.
app.service('myService', function($http, $rootScope) {
this.names=[]
});
app.controller('current', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.names=myService.names;
console.log($scope.names);
}]);
Can you please help. How should I make the current controller update the data once the $scope.names variable in the select controller is updated?
According to me what I am doing should work :-/
There are many way to archive this:
First:
By watching for the service variable data change
var app = angular.module('plunker', []);
app.service('dataService', function() {
this.serviceData = "test";
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.serviceData = mainData;
}
});
app.controller('SubCtrl', function($scope, dataService) {
$scope.name = 'World';
$scope.getServiceData = function() {
return dataService.serviceData;
}
$scope.$watch("getServiceData()", function(newValue, oldValue) {
if (oldValue != newValue) {
$scope.name = newValue;
}
});
});
http://plnkr.co/edit/G1C81qvDD179NILMMxWb
Second:
Using event broadcast
var app = angular.module('plunker', []);
app.factory('dataService', function($rootScope) {
var serviceData = {
"mydata": "test"
};
$rootScope.$watch(function() {
return serviceData.mydata;
}, function(newValue, oldValue, scope) {
$rootScope.$broadcast('dataService:keyChanged', newValue);
}, true);
return serviceData;
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.mydata = mainData;
}
});
app.controller('SubCtrl', function($scope, $rootScope, dataService) {
$scope.name = 'World';
$rootScope.$on('dataService:keyChanged', function currentCityChanged(event, value) {
console.log('data changed', event, value);
$scope.name = value;
});
});
http://plnkr.co/edit/tLsejetcySSyWMukr89u?p=preview
Third:
Using callback
var app = angular.module('plunker', []);
app.service('dataService', function() {
var serviceData = "test";
var callback = null;
this.updateServiceData = function(newData){
serviceData = newData;
if(null!==callback)
{
callback();
}
};
this.getServiceData = function(){
return serviceData;
};
this.regCallback = function(dataCallback){
callback = dataCallback;
};
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.updateServiceData(mainData);
}
});
app.controller('SubCtrl', function($scope, dataService) {
$scope.name = 'World';
$scope.dataChangeCalback = function() {
$scope.name = dataService.getServiceData();
}
dataService.regCallback($scope.dataChangeCalback);
});
http://plnkr.co/edit/vrJM1hqD8KwDCf4NkzJX?p=preview
One way to do this is we can bind the entire service to the scope:
myApp.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.myService = myService;
$scope.click = function () {
myService.names = "john";
};
And then we change the myService.names directly
current controller should look like this:
myApp.controller('current', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.names=myService.names;
console.log($scope.names);
$scope.$watch(function() { return myService.names; }, function(newVal, oldVal) {
$scope.names = newVal;
});
}]);
}]);
We then use a watcher expression.
or a watcherExpression See for more details.
Structure
statsController.js
(function (module) {
'use strict';
var statsController = function ($scope, $rootScope, $timeout, $routeParams, $location, $window, statsService) {
$scope.$on('$viewContentLoaded', function (event) {
$window.ga('send', 'pageview', { page: $location.url() });
});
var model = {};
model.stats = {};
statsService.getStats().then(function (d) {
model.stats = d;
});
};
module.controller("statsController", statsController);
}(angular.module("app")));
statsService.js
(function (app) {
var statsService = function (webapi) {
var model = {};
model.getStats = function () {
return webapi.get('stats/getstats');
}
return model;
};
app.factory("statsService", statsService);
statsService.$inject = ['webapi'];
}(angular.module("app")))
stats.html
Total paid customers: {{statsController.model.totalPaidCustomers}}<br/>
Stripe confirmed customers: {{statsController.model.stripeConfirmedCustomers}}<br />
Result from API:
{"totalPaidCustomers":1,"stripeConfirmedCustomers":2}
When I put alert() in statsController.js for d.totalPaidCustomers I get value 1, same for other parameter.
So only problem is to show this in html.
App.js
.when('/stats', {
templateUrl: 'tpl/admin/stats.html',
controller: 'statsController',
controllerAs: 'stats'
}).
If i understand correctly. It should be "model.stats"
Total paid customers: {{statsController.model.totalPaidCustomers}}
http://jsfiddle.net/f5hb9spz/8/
Try changing your state definition to this:
.when('/stats', {
templateUrl: 'tpl/admin/stats.html',
controller: 'statsController',
controllerAs: 'vm'
}).
Then change the controller to this:
(function (module) {
'use strict';
var statsController = function ($scope, $rootScope, $timeout, $routeParams, $location, $window, statsService) {
$scope.$on('$viewContentLoaded', function (event) {
$window.ga('send', 'pageview', { page: $location.url() });
});
var vm = this;
vm.model = {};
vm.model.stats = {};
statsService.getStats().then(function (d) {
vm.model.stats = d;
});
};
module.controller("statsController", statsController);
}(angular.module("app")));
Finally your view goes to this:
Total paid customers: {{vm.model.stats.totalPaidCustomers}}<br/>
Stripe confirmed customers: {{vm.model.stats.stripeConfirmedCustomers}}<br />
If you don't see anything then just put this in the view and see what you have:
{{ vm | json }}
Problem was I didn't assign the current scope to a model.
var model = this;
statsController.js
(function (module) {
'use strict';
var statsController = function ($scope, $rootScope, $timeout, $routeParams, $location, $window, statsService) {
$scope.$on('$viewContentLoaded', function (event) {
$window.ga('send', 'pageview', { page: $location.url() });
});
var model = this;
model.stats = {};
statsService.getStats().then(function (d) {
model.stats = d;
});
};
module.controller("statsController", statsController);
}(angular.module("app")));
Then call in html:
Total paid customers: {{stats.stats.totalPaidCustomers}}<br/>
Stripe confirmed customers: {{stats.stats.stripeConfirmedCustomers}}<br />
have to change name of var though(stats.stats), confused the hell out of me.
I am working on a mobile application that gets a list of jobs from the server (WEBAPI) and populates the proper fields. When the user clicks on the job name, the application goes to a details page, where the job information needs to show again.
I am having issues getting the information to show.
Here is the index:
.state('jobs',{
abstract: true,
url: '/jobs',
templateUrl: 'modules/jobs/views/jobs.html',
controller: ['$scope', '$state', '$stateParams', 'jobs', function($scope, $state, $stateParams, jobs) {
jobs.getData()
.then(function(jobs) {
$scope.jobs = jobs;
});
}]
})
// Jobs > List
.state('jobs.list', {
url: '',
title: 'All Jobs',
templateUrl: 'modules/jobs/views/jobs.list.html'
})
// Jobs > Detail
.state('jobs.detail', {
url: '/{JobId:[0-9]{1,4}}',
title: 'Job Details',
views: {
'details': {
templateUrl: 'modules/jobs/views/jobs.detail.html',
controller: ['$scope', '$state', '$stateParams', 'utils', function($scope, $state, $stateParams, utils) {
$scope.job = utils.findById($scope.jobs, $stateParams.JobId);
$scope.edit = function(){
$state.go('.edit', $stateParams);
};
}]
},
'': {
templateUrl: 'modules/jobs/views/jobs.materials.html',
controller: ['$scope', 'materials', '$stateParams', function($scope, materials, $stateParams) {
materials.getDataById($stateParams.JobId)
.then(function(materials) {
$scope.materials = materials;
});
$scope.subHeader = 'Bulk Sack Materials';
}]
}
}
})
Here is the Service:
app.factory('jobs', ['$resource', '$q', '$http', 'localStorageService', function($resource, $q, $http, localStorageService) {
localStorageService.set('SessionId', 'A00DB328-7F9C-4517-AD5D-8EAA16FBBC8F');
var SessionId = localStorageService.get('SessionId');
return {
getData: function() {
var deferred = $q.defer();
$http.get(baseUrl + 'Job/GetJobs?SessionId=' + SessionId, {
cache: true
}).success(function(jobs) {
deferred.resolve(jobs);
});
return deferred.promise;
}
};
}]);
app.factory('materials', ['$resource', '$q', '$http', 'localStorageService', function($resource, $q, $http, localStorageService) {
var SessionId = localStorageService.get('SessionId');
return {
getDataById: function(id) {
var deferred = $q.defer();
$http.get(baseUrl + 'Material/GetMaterials/' + id + '?SessionId=' + SessionId, {
cached: 'true'
}).success(function(materials) {
deferred.resolve(materials);
});
return deferred.promise;
}
};
}]);
And here is the utils service:
app.factory('utils', function() {
return {
findById: function findById(a, id) {
for (var i = 0; i < a.length; i++) {
if(a[i].id === id) {
return a[i];
}
}
return null;
}
};
});
Here is the HTML for the job.list:
<div class="list-group">
<a class="list-group-item" ng-repeat="job in jobs" ui-sref="jobs.detail({ JobId: job.JobId })">
<dl>
<dt>{{job.Name}}</dt>
<dd>{{job.Location}}</dd>
</dl>
Some insight on how to get this to work would be awesome.
Thank You-
If I have inferred your goal correctly, you're issue is on the following line:
$scope.job = utils.findById($scope.jobs, $stateParams.JobId);
$scope.jobs will not exist like you expect it to. The jobs object was created in the list view's controller's scope, not the details view's controller. You'll want to do something like you have in the '' controller
JobService.getJobById($stateParams.JobId).then(function(data) {
$scope.job = data;
});
i am using one of the basic concept of angularjs that child controller inherit from parent controller. so i have writen the following code :
var editChannelCtrl = function ($scope, $route, $location, youtube) {
$scope.loading = false;
$scope.saved = false;
$scope.errors = [];
if (angular.isDefined($route.current.params.id)) {
$scope.isOldChannel = true;
$scope.isNewChannel = false;
} else {
$scope.isNewChannel = true;
$scope.isOldChannel = false;
}
};
editChannelCtrl.$inject = ['$scope', '$route', '$location', 'youtube'];
editChannelCtrl.resolve = {
channel: ['ServiceChannel' , function (ServiceChannel) {
return ServiceChannel.ChannelLoader();
}]
};
var oldChannelCtrl = function ($scope, $location, channel) {
$scope.channel = channel;
};
oldChannelCtrl.$inject = ['$scope' , '$location', 'channel'];
var newChannelCtrl = function ($scope, $location, Channel) {
$scope.channel = {
id: null,
version: 1
};
};
newChannelCtrl.$inject = ['$scope' , '$location', 'Channel'];
and for routes what i do , that i resolve the channel that load the channel for the edit form with the following code.
.when('/admin/refactor/channel/edit/:id', {
controller: editChannelCtrl,
templateUrl: '/admin/assets/views/channelForm.html',
resolve: editChannelCtrl.resolve
})
.when('/admin/refactor/channel/new', {
controller: editChannelCtrl,
templateUrl: '/admin/assets/views/channelForm.html'
})
but i don't know why angularjs don't figure how to inject channel to oldChannelCtrl ?