I know this is easy, but I can't quite wrap my head around how to do this.
I need to do the API call within a service so that those variables can be accessed between two separate controllers.
The problem I am having is I can't access $routeParams (which I need for the get) within the service. I can't figure out know how to pass $routeParams from the controller to the service.
app.controller('Main', ['$scope', 'Page', '$routeParams', '$http', function($scope, Page, $routeParams, $http) {
$scope.Page = Page;
}]);
app.controller('Pages', ['$scope', 'Page', '$routeParams', '$http', function($scope, Page, $routeParams, $http) {
$scope.Page = Page.posts;
}]);
app.factory('Page', ['$routeParams', '$http', function($routeParams, $http) {
var posts = function posts() {
$http.get('wp-json/wp/v2/pages/?filter[name]='+ $routeParams.slug).success(function(res){
console.log(JSON.stringify(res) );
});
};
var description = '';
var title = '';
return {
title: function () { return title; },
setTitle: function (newTitle) { title = newTitle; },
description: function () { return description; },
setDescription: function (newDescription) { description = newDescription; },
posts
};
}]);
factory :
app.factory('Page', ['$http', function($http) {
var _posts = function posts(param) {
return $http.get('wp-json/wp/v2/pages/?filter[name]='+ param);
};
var description = '';
var title = '';
return {
title: function () { return title; },
setTitle: function (newTitle) { title = newTitle; },
description: function () { return description; },
setDescription: function (newDescription) { description = newDescription; },
posts : _posts
};
}]);
Controller :
app.controller('Pages', ['$scope', 'Page', '$routeParams', '$http', function($scope, Page, $routeParams, $http) {
Page.posts($routeParams.slug).then(function success(response) {
$scope.Page = response.data;
}, function error(reason) {
// do something
});
}]);
please note that success is deprecated in newer versions of Angular. I have updated the code with then
Related
How do I include ui.bootstrap. I use ui.bootstrap to open the bootstrap modal(open) on ng-click. After that I want to send all modal data to server, for that I use $http in my angular controller. But it gives an error. Below is my angular js code.
var app = angular.module("modalFormApp", ['ui.bootstrap']);
app.controller("modalAccountFormController", ['$scope', '$modal', '$log', '$http'
function($scope, $modal, $log, $http) {
$scope.showForm = function() {
$scope.message = "Show Form Button Clicked";
console.log($scope.message);
var modalInstance = $modal.open({
templateUrl: 'modal-form.html',
controller: ModalInstanceCtrl,
scope: $scope,
resolve: {
userForm: function() {
return $scope.userForm;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
]);
app.controller('ModalInstanceCtrl', ['$scope', '$http', '$modalInstance', userForm, function($scope, $http, $modalInstance, userForm) {
//var ModalInstanceCtrl = function ($scope, $modalInstance,$http, userForm) {
$scope.form = {}
$scope.url = 'submit.php';
$scope.submitForm = function() {
if ($scope.form.userForm.$valid) {
$http.post($scope.url, {
"name": $scope.name,
"email":
$scope.email,
"message": $scope.message
}).
success(function(data, status) {
console.log(data);
$scope.status = status;
$scope.data = data;
$scope.result = data;
})
} else {
console.log('userform is not in scope');
}
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}])
'ui.bootstrap' has prerequisites 'ngAnimate' and 'ngTouch'. You should add them to your module
var app = angular.module("modalFormApp", ['ngAnimate','ngTouch','ui.bootstrap']);
And you should add their scripts to your view
script(src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.min.js")
script(src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-touch.min.js")
Say i have the following factory:
app.factory("categoryFactory", function (api, $http, $q) {
var selected = null;
var categoryList = [];
return {
getList: function () {
var d = $q.defer();
if(categoryList.length <= 0){
$http.get(api.getUrl('categoryStructure', null))
.success(function (response) {
categoryList = response;
d.resolve(categoryList);
});
}
else
{
d.resolve(categoryList)
}
return d.promise;
},
setSelected: function (category) {
selected = category;
},
getSelected: function () {
return selected;
}
}
});
now i have two controllers using this factory at the same time. Because of this both controllers has to be notified when updated for this i attempted the following:
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api','categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
$scope.selectedCategory = categoryFactory.getSelected();
}]);
While my other controller looks like this:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
$scope.categories = [];
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
$scope.selectCategory = function (category) {
categoryFactory.setSelected(category);
}
}]);
how ever when the NavController changed the value it was not changed in the DashboardController
My question is how can i either watch or in another way get notified when the value changes?
You can use an observer pattern, like so:
app.factory("categoryFactory", function (api, $http, $q) {
// the list of callbacks to call when something changes
var observerCallbacks = [];
// ...
function notifyObservers() {
angular.forEach(observerCallbacks, function(callback) {
callback();
});
}
return {
setSelected: function (category) {
selected = category;
// notify the observers after you change the value
notifyObservers();
},
registerObserver: function(callback) {
observerCallbacks.push(callback);
}
}
});
And then in your controllers:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
// ...
// init
(function() {
categoryFactory.registerObserver(function() {
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
});
})();
}]);
This way, any time setSelected is called, it calls each callback that you've registered in observerCallbacks. You can register these from any controller since factories are singletons and they will always be in the know.
Edit: just want to add that I may have put the notifyObservers() call in the wrong area (currently in setSelected) and that I may be putting the wrong update call in the controller (currently getList) but the architecture remains the same. In the registerObserver, put whatever you want to do when the values are updated and wherever you make changes that you want observers to know about call notifyObservers()
You could follow dot rule here so that prototypal inheritance will get followed.
Basically you need to have one object inside your service that will have selected variable, And will get rid of getSelected method.
Factory
app.factory("categoryFactory", function(api, $http, $q) {
var categoryFactory = {};
categoryFactory.getList = function() {
var d = $q.defer();
if (categoryList.length <= 0) {
$http.get(api.getUrl('categoryStructure', null))
.success(function(response) {
categoryList = response;
d.resolve(categoryList);
});
} else {
d.resolve(categoryList)
}
return d.promise;
}
categoryFactory.setSelected = function(category) {
categoryFactory.data.selected = category;
}
categoryFactory.data = {
selected: null
}
return categoryFactory;
});
Controller
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'categoryFactory',
function($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
//this will provide you binding without watcher
$scope.selection = categoryFactory.data;
}
]);
And then use {{selection.selected}} on html part will update a value when changes will occur in selection.
I want to call a method from one controller to another controller. There are two controllers named "header" and "mainContent". Need to call a "trigger method" in the "header Controller", After the success call of "result method" in the mainController.
If that method called that should hide that paragraph.
<div ng-controller="header">
<p ng-show="msg">Content</p>
</div>
<div ng-controller="mainContent">
</div>
var module = angular.module("sourceViewer", ['ui.router']);
//header controller
module.controller('header', function ($scope, $location) {
$scope.msg=true;
$scope.trigger= function(data) { //This method should be called after the result method called in the mainContent Controller
$scope.$on('UPDATE_CHILD', function() {
if(data)
$scope.msg=false;
});
}
});
// mainContent controller
module.controller('mainContent', function ($scope, $location, dataService) {
$scope.user = dataService.user;
$scope.signIn = function (user) {
var result = dataService.login(user);
result.success(function (data) {
if (data.message== "success") {
$scope.$broadcast('UPDATE_CHILD');
//From here I want to call trigger method of header controller
}
})
};
});
did u try this?
module.controller('header', ['$scope', '$location', '$rootScope', function ($scope, $location, $rootScope) {
$scope.msg=true;
$scope.trigger= function(data) {
if(data)
$scope.msg=false;
};
$rootScope.$on('event:fire', $scope.trigger);
}]);
// mainContent controller
module.controller('mainContent', ['$scope', '$location', 'dataService', function ($scope, $location, dataService) {
$scope.user = dataService.user;
$scope.signIn = function (user) {
var result = dataService.login(user);
result.success(function (data) {
if (data.message== "success") {
$rootScope.$broadcast('event:fire');
}
})
};
}]);
You can use $rootScope like:
<div ng-controller="header">
<p ng-show="$root.header.msg">Content</p>
</div>
<div ng-controller="mainContent">
</div>
var module = angular.module("sourceViewer", ['ui.router']);
//header controller
module.controller('header', function ($rootScope,$scope, $location) {
$rootScope.header.msg = true;
});
// mainContent controller
module.controller('mainContent', function ($rootScope,$scope, $location, dataService) {
$scope.user = dataService.user;
$scope.signIn = function (user) {
var result = dataService.login(user);
result.success(function (data) {
if (data.message== "success") {
$rootScope.header.msg = true;
}
})
};
});
in the follwoing code you can see headerController is calling alert in mainController
myApp = angular.module("myApp",[]);
myApp.service("myService", function(){
showAlertBool = false;
return {
showAlert: function (value) {
showAlertBool = value;
},
canShowAlert: function () {
return showAlertBool;
}
}
});
myApp.controller("headerController", function($scope, myService){
console.log(myService);
$scope.clickHandler = function(){
myService.showAlert(true);
}
});
myApp.controller("mainController", function($scope, myService){
console.log(myService);
$scope.getServiceValue = function(){
return myService.canShowAlert();
}
$scope.$watch("getServiceValue()", function(newValue, oldValue){
if(newValue === true && newValue !== oldValue){
myService.showAlert(false);
alert("I can show Alert now!!!");
}
});
});
For a working code you can go here
I have an angular controller called SubmissionTreeController and it has update_dashboard() function which refreshes the ui every minute.
My goal is to refresh the ui on successful post request from a different controller.
How do I make this function available in other controllers?
var module = angular.module("submissionDashboard", ['ui.tree', 'ngCookies', 'ui.bootstrap',]);
module.controller("SubmissionTreeController", ["$scope", "$http", "$modal",
function($scope, $http, $modal) {
$scope.selected_items = {};
var update_dashboard = function() {
var url = Django.url('submission:active_list_ajax', {
site : site
});
$http.get(url).success(function(data) {
$scope.list = data.results;
});
};
update_dashboard();
$scope.closeTask = function(scope) {
var modalInstance = $modal.open({
templateUrl: 'modal_close_submission_renderer.html',
controller: 'ModalCloseSubmissionController',
resolve: {
items: function () {
return $scope.selected_items;
}}
});
};
}]);
module.controller('ModalCloseSubmissionController', ['$scope', '$modalInstance', '$http', 'items', function ($scope, $modalInstance, $http, items) {
$scope.items = items;
$scope.selected = {
item: 1,
text: ''
};
$scope.ok = function () {
var val = $scope.selected.item;
if (val === 1) {
var url = Django.url('submission:close-notify', {
site : site
});
$http.post(url, $scope.selected_items).success(function(data) {
update_dashboard();
});
} else if (val === 2) {
var url = Django.url('submission:close', {
site : site
});
$http.post(url, $scope.selected_items).success(function(data) {
update_dashboard();
});
} else if (val === 3) {
var url = Django.url('submission:cancel', {
site : site
});
$http.post(url, $scope.selected_items).success(function(data) {
update_dashboard();
});
};
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
Edit:
What I am trying to do:
module.service('updateDashboardService', function($scope, $http){
this.update_dashboard = function() {
$scope = $scope;
var url = Django.url('submission:active_list_ajax', {
site : site
});
$http.get(url).success(function(data) {
$scope.list = data.results;
});
};
});
module.controller("SubmissionTreeController", ["$scope", "$http", "$modal", "updateDashboardService", function($scope, $http, $modal, updateDashboardService) {
$scope.selected_items = {};
updateDashboardService.update_dashboard();
var timer = setInterval(function() {
$scope.$apply(updateDashboardService.update_dashboard($scope, $http));
}, 1000 * 60);
What I am getting:
Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- updateDashboardService
Edit 2:
module.service('updateDashboardService', function($rootScope, $http){
this.update_dashboard = function() {
var url = Django.url('submission:active_list_ajax', {
site : site
});
$http.get(url).success(function(data) {
$rootScope.list = data.results;
});
};
});
As #Gopesh says create a factory method, or, you can do something like this in SubmissionTreeController:
$scope.$on("event:updateDashboard", function(){ update_dashboard() });
And in your other controller:
$http.post(url, $scope.selected_items).success(function(data) {
$scope.$emit("event:updateDashboard");
});
I was following a question (ui bootstrap modal's controller 'is not defined'), which I then tried modifying for nested controllers, different scoping calls, and renaming/refactoring the code (for learning).
I couldn't get it working in My Plunker, so that leaves me with a few questions:
Why is it not working?
The original question shows creating a new module, rather than appending controllers to the app module -- why? Is this recommended?
If PageController is the ancestor controller, how would it's $scope.open method reference the other controllers open definition?
Code:
var app = angular.module('app', ['ui.bootstrap']);
app.controller('PageController', ['$scope',
function($scope) {
$scope.open = function() {
// how to call ModalController.open?
};
}
])
.controller('ModalController', ['$scope', '$modal', '$log',
function($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function() {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function() {
return $scope.items;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
])
.controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'items',
function($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
]);