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
Related
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
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'm trying to call the mergeUserList() function that is inside my service. I do this is my controller that looks like this:
app.controller('UserManagementController', ['$http','$sessionStorage','api','$modal','$scope','Session', 'divisionService','$filter', function ($http, $sessionStorage, api, $modal, $scope, $state, Session, divisionService,$filter) {
divisionService.mergeUserList().then(function(response)
{
$scope.users = response;
});
}]);
And my service:
app.factory("divisionService", function (api, $http, $q) {
//Organization divisions with division users
var division = {};
var divisionArray = [];
var mergedUserList = [];
return {
mergeUserList: function () {
if (divisionArray == null || divisionArray.length == 0) {
var list = [];
var d = $q.defer();
this.getList().then(function () {
divisionArray.forEach(function (y) {
y.users.forEach(function (user) {
list.push(user);
});
d.resolve(list);
})
});
return d.promise;
}
else {
return null;
}
}
};
return division;
});
My problem is that when i run the code it says TypeError: undefined is not a function in line 1 in the controller. I know for a fact that the problem is not in the service, becuase I use it in another controller, and there it works.
You have one $state as a function argument which is not included in the array, change it to:
app.controller('UserManagementController', ['$http','$sessionStorage','api','$modal','$scope', '$state', 'Session', 'divisionService','$filter', function ($http, $sessionStorage, api, $modal, $scope, $state, Session, divisionService, $filter) {
I'm writing a controller. This controller has to communicate with an other controller. But I don't know is it posible?
HTML:
<div data-ng-app="TestApp">
<div data-ng-controller="menuCtrl">
<ul>
<li> <a data-ng-click="Click()">
MenĂ¼1</a>
</li>
</ul>
</div>
<div data-ng-controller="pageCtrl">
<hr/>
<button data-ng-click="getText()">GetText</button>
<br/>
<strong data-ng-model="boldText"> {{boldText}}</strong>
</div>
JS:
var app = angular.module('TestApp', []);
app.controller('menuCtrl', function ($rootScope, $scope) {
$scope.Click = function () {
//???
};
})
.controller('pageCtrl', function ($rootScope, $scope) {
$scope.getText = function () {
$scope.boldText = 'tst';
};
});
I repaired sample on JSfiddle:sample
You can easily achieve that with broadcasting:
var app = angular.module('TestApp', []);
app.controller('menuCtrl', function ($rootScope, $scope) {
$scope.Click = function () {
$scope.$broadcast('MyClickEvent', {
someProp: 'Clicking data!' // send whatever you want
});
};
})
.controller('pageCtrl', function ($rootScope, $scope) {
$scope.getText = function () {
$scope.boldText = 'tst';
};
$scope.$on('MyClickEvent', function (event, data) {
console.log(data); // 'Data to send'
});
});
Using the events broadcast, we can pass the value form one controller to another
app.controller('menuCtrl', function ($rootScope, $scope) {
$scope.Click = function () {
var valueToPass = "value";
$rootScope.$broadcast('eventMenuCtrl', valueToPass);
};
})
.controller('pageCtrl', function ($rootScope, $scope) {
$scope.getText = function () {
$scope.boldText = 'tst';
};
$scope.$on('eventMenuCtrl', function(event, value) {
$scope.boldText = value;
})
});
http://jsfiddle.net/q2yn9jqv/4/
I have created some search functionality with Angular js.
showing the HTML content using ngSanitize. Now in the HTML data I want to use jQuery onClick().
I tried a lot but no luck something is wrong:
Below is the Angular controls' code:
var myApp = angular.module('myApp', ['ngSanitize']);
myApp.factory('Items', ['$http', function($http){
return {
get: function(callback){
$http.get('assets/script/items.json').success(function(data){
callback(data);
})
}
}
}]);
myApp.factory('Categories', ['$http', function($http){
return {
get: function(callback){
$http.get('assets/script/categories.json').success(function(data){
callback(data);
})
}
}
}]);
// Config and Routes
myApp.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl:"home.html"
})
.when('/item/:id', {
templateUrl:"item.html"
})
})
myApp.controller('headerController', function($scope, $location) {
$scope.goHome = function () {
$location.path('/');
};
})
function controller($scope) {
$scope.greeting = 'hello';
}
// Controllers
myApp.controller('ItemController', function($scope, $route, $location, $http, Items){
Items.get(function(response){
$scope.items = response;
});
// Update this value dynamically - onclick
$scope.filters = "food";
$scope.viewDetail = function(item) {
$location.path('/item/' + item.id);
}
})
myApp.controller('ListController', function($scope, $route, $location, $http, Categories){
$scope.sendCategory = function(category) {
// How can I pass this value to ItemController?
$scope.search =category.name;
};
$scope.orderProp='title';
$scope.tab = function (tabIndex) {
//Sort by date
if (tabIndex == 1){
//alert(tabIndex);
$scope.orderProp='date';
}
//Sort by views
if (tabIndex == 2){
$scope.orderProp = 'views';
}
};
$scope.sort = function(item) {
if ( $scope.orderProp == 'date') {
return new Date(item.date);
}
return item[$scope.orderProp];
}
})
myApp.controller('CategoryController', function($scope, $route, $location, $http, Categories){
Categories.get(function(response){
$scope.categories = response;
});
})
myApp.controller("tabsController", function ($scope) {
$scope.orderProp = 'date';
})
myApp.controller('ItemDetailController', function($scope, $route, $location, $http, Items){
$scope.goHome = function () {
$location.path('/');
};
Items.get(function(response){
$scope.items = response;
if ($route.current.params.id) {
angular.forEach($scope.items, function (v, k) {
if (v.id == $route.current.params.id) {
$scope.currItem = $scope.items[k];
return false;
}
});
}
});
})
jSon Data sample:
[
{
"id": 1,
"title": "My Title",
"src": "assets/images/myPic.jpg",
"description": "<p>Hello p tag</p><h2>heading</h2><div>Content</div>",
"organization": "My Organization",
"currentrole": "My Current Role"
},
{
"id": 2,
"title": "My Title",
"src": "assets/images/myPic2.jpg",
"description": "<p>Hello p tag 2</p><h2>heading2</h2><div>Content 2</div>",
"organization": "My Organization",
"currentrole": "My Current Role"
}
]
Please help! Thanks in advance.
Why would you use jquery for a click event, You can use Angular ng-click event to bind any html element to an angular $scope function. Look at the docs:
Angular ngClick
You could also use standard javascript
var someelement = document.getElementById("myelement");
someelement .addEventListener("click",function(e){
//Insert code
},false);
here is the code what I meant:
myApp.controller('ItemDetailController', function($scope, $route, $location, $http, Items){
$scope.goHome = function () {
$location.path('/');
};
Items.get(function(response){
$scope.items = response;
if ($route.current.params.id) {
angular.forEach($scope.items, function (v, k) {
if (v.id == $route.current.params.id) {
$scope.currItem = $scope.items[k];
return false;
}
});
}
});
$('.detailed').on('click', 'h4', function(){
$(this).next('ul').slideToggle();
$(this).toggleClass('activeHead');
});
})