AngularJS exchange Data between two Modules - angularjs

I created 2 HTML pages as Angular modules.
var app = angular.module("oneApp", []);
app
.controller(
'controller-one',
[
'$scope',
'$http',
function($scope, $http) {...functions..}]);
Both how different controllor files. But now I need this two controllers to exchange some data.
I found this related question in SO : related Thread
When trying to changing on controllor to that..
var app = angular.module("oneApp", ['twoAoo']);
.. I get an injection error. I think that's because both file are not related.
How to accomplish to exchange data correctly?

To share data between two modules, you need to use a service.
var otherApp = angular.module('otherApp', []);
otherApp.factory('myService', function() {
var myService = {
someData: ''
};
return myService;
});
otherApp.controller('otherCtrl', function($scope, myService) {
$scope.shared = myService;
});
var app = angular.module('myApp', ['otherApp']);
app.controller('myCtrl', function($scope, myService) {
$scope.shared = myService;
});
This article can help you further: https://thinkster.io/a-better-way-to-learn-angularjs/services

As #Penman said, you should use a service (here, I used a factory).
A very simple use case is to have a service with a method that log something. Then we use this service from 2 different modules.
Here's how I did it :
index.html
<body>
<div ng-app="appOne">
<div ng-controller="appOneCtrl">
{{ name }} <button ng-click="log()">Log</button>
</div>
<div ng-app="appTwo">
<div ng-controller="appTwoCtrl">
{{ name }} <button ng-click="log()">Log</button>
</div>
</div>
</div>
</body>
script.js
// APP 1
const app1 = angular.module('appOne', ['appTwo']);
app1.controller('appOneCtrl', function($scope, $log, sharedFactory) {
$scope.name = 'App 1, ctrl 1';
$scope.log = () => {
$log.info('Click on log button from appOne');
sharedFactory.logMeSomething();
};
});
// -----------------------------------------
// APP 2
const app2 = angular.module('appTwo', []);
app2.controller('appTwoCtrl', function($scope, $log, sharedFactory) {
$scope.name = 'App 2, ctrl 2';
$scope.log = () => {
$log.info('Click on log button from appTwo');
sharedFactory.logMeSomething();
};
});
app2.factory('sharedFactory', function($log) {
return {
logMeSomething: () => {
$log.debug('Something logged from sharedFactory !');
}
};
});
Clicking on "Log 1" button displays :
Click on log button from appOne
Something logged from sharedFactory !
Clicking on "Log 2" button displays :
Click on log button from appTwo
Something logged from sharedFactory !
Here's a working Plunkr of my solution :
https://plnkr.co/edit/sgOKkh0eh0URPGIP9dZY?p=preview

Related

How to call a method from a controller to another controller in angular js

I have a view for SidebarController like below -
<a ng-click="reachMe($event);$event.preventDefault()" ng-href="#/app/hello">
Before going to the link I want to call reachMe() to check some changes on page and need to show an alert if any changes made
function SidebarController($rootScope, $scope, $state, $location, SidebarLoader){
$scope.reachMe = function(event){
//here I want to call function isPageChanged() from StaticPageController
//something like this
// if StaticPageController.isPageChanged() return true
// then show alert
// else
// $location.url($href)
}
}
Update 1 :
Not sure about this, But give it a try.
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.reachMe = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
if($rootScope.isChanged){
// Show Alert
}else{
//Go to route
}
}
});
app.controller('ControllerTwo', function($scope, $rootScope,$state) {
$scope.checkSomethingChanged = function() {
alert("Hello");
$rootScope.isChanged = true;
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.checkSomethingChanged();
});
});
Following method worked for me perfectly :
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.methodA = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
}
});
app.controller('ControllerTwo', function($scope, $rootScope) {
$scope.reachMe = function() {
alert("Hello");
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.reachMe();
});
});
</script>
A controller is not the right concept for sharing functionality. Use a Factory or Service for that.
var logicFactory = function () {
return {
methodA: function () {
},
methodB: function()
{
}
};
}
You can then inject that factory into each controller where it is needed like:
var ControllerA = function ($scope,logicFactory) {
$scope.logic = logicFactory;
}
ControllerA.$inject = ['$scope', 'logicFactory'];
Another option is to use the broadcast/emit Patern. But I would use that only where really necessary:
Usage of $broadcast(), $emit() And $on() in AngularJS

Making an API call with every Angular ng-click

I'm new to web development and can't seem to find the answer to this question anywhere. I want my NodeJS API endpoint to be called with every ng-click, not just when the page gets loaded. Here is what I have so far:
HTML:
<button ng-click="myFunction()">Click me!</button>
Angular:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.post("/test").then(function(response) {
$scope.testString = response.data;
});
});
NodeJS
app.get('/test', function(req, res) {
console.log("test get");
});
Is this what you're looking for?
HTML:
<button ng-click="myFunction()">Click me!</button>
Angular:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$scope.myFunction = function() {
$http.post("/test").then(function(response) {
$scope.testString = response.data;
});
}
});

Passing value between controllers in AngularJS

As stated in the title, I'm trying to pass a value (ID) from one controller (PerksApprovalController) going to another controller (PerksDetailsController). Please find below image for visual reference.
What I want to do is, when I click the "Show Details" button, it will redirect me to another page to display the details of the Control Number that I pass.
Below is my implementation.
Show Details Button Code
<button class="btn btn-xs" ng-click="vm.showDetails(p.ControlNumber)">Show Details</button>
PerksApprovalCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksApprovalController.$inject = ['$window', 'app.perksService', 'app.sharedValuesFactory'];
app.controller('app.perksApprovalController', PerksApprovalController);
function PerksApprovalController($window, PerksService, SharedValuesFactory) {
/* jshint validthis:true */
var vm = this;
vm.showDetails = function (controlNo) {
SharedValuesFactory.setControlNo(controlNo);
$window.location = '/PerksDetails/PerksView';
}
}
})();
PerksDetailCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksDetailController.$inject = ['$scope', '$http', '$q', '$window', 'app.perksService', 'app.sharedValuesFactory'];
app.controller('app.perksDetailController', PerksDetailController);
function PerksDetailController($scope, $http, $q, $window, PerksService, SharedValuesFactory) {
var vm = this;
PerksService.getPerksItems(SharedValuesFactory.getControlNo()).then(function (response) {
vm.perksItemDetails = response.data;
});
}
})();
I have created a service just like what they suggested in some topics here.
sharedValuesFactory.js
(function () {
'use strict';
var app = angular.module('app');
// SharedValuesFactory.$inject = ['$http'];
app.factory('app.sharedValuesFactory', SharedValuesFactory);
function SharedValuesFactory() {
var controlNoShared;
return {
setControlNo: function (c) {
this.controlNoShared = c;
},
getControlNo: function () {
return this.controlNoShared;
}
}
}
})();
My problem now is, everytime the details page is loaded, SharedValuesFactory.getControlNo() returns undefined. Looks like SharedValuesFactory is reset after the redirect or page load.
Any idea on how to properly pass a value from one controller to another?
TIA
I have a specific way of passing value in between Controllers. Hope it does the trick!
Note:
Not Sure what sharedValuesFactory.js is being used for! Assumming You are using this service to pass Data in between Controllers only. According to me only One service suites your requirement i.e PerksService.
The button passes the value (ID) of "ControlNumber".
<button class="btn btn-xs" ng-click="vm.showDetails(p.ControlNumber)">Show Details</button>
In PerksApprovalCtrl.js pass the controlNo you are getting on button click to the url of the page as in of a different view
PerksApprovalCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksApprovalController.$inject = ['$window', 'app.perksService'];
app.controller('app.perksApprovalController', PerksApprovalController);
function PerksApprovalController($window, PerksService) {
/* jshint validthis:true */
var vm = this;
vm.showDetails = function (controlNo) {
$window.location = ;
$location.path('/PerksDetails/PerksView'+controlNo);
}
}
})();
In Routes.js or the place where you define the routes of your angular application add the following lines:
.when('/PerksDetails/PerksView/:controlNo', {
templateUrl: '<YOU DEFINE THE TEMPLATE>',
controller: 'PerksDetailController',
reloadOnSearch: false })
Here ":controlNo" is used to pass the value you are passing in the url from PerksApprovalController.
In PerksDetailController we get the controlNo from routeParams and pass it to your PerksService to get the details from it.
PerksDetailCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksDetailController.$inject = ['$scope', '$http', '$q', '$window', '$routeParams', 'app.perksService'];
app.controller('app.perksDetailController', PerksDetailController);
function PerksDetailController($scope, $http, $q, $window, $routeParams, PerksService) {
var vm = this;
PerksService.getPerksItems($routeParams.controlNo).then(function (response) {
vm.perksItemDetails = response.data;
});
}
})();
Hope it Solves your problem! Thank You!

Passing Data Between Controllers - Frustrated by lack of clarity in other answers

Like many before I want to pass data between controllers. Specifically I want the user to be able to keep track of creating another user. I looked at the following SO explanations and came away not getting the results I was looking for or with answers that I don't know how to implement:
How can I pass some data from one controller to another peer controller
angularjs - passing data between controllers
AngularJS: How can I pass variables between controllers?
I also don't think broadcast is the solution to the problem. I think this is something that should be done with a service or factory (either will do as long as it works since I don't really understand the difference between them right now)
My code:
SERVICE
angular.module('startupApp')
.service('vendorId', function () {
// AngularJS will instantiate a singleton by calling "new" on this function
var VendorId = [];
var Vendor = [];
return {
setVendorId: function(vendorId){
VendorId.push(vendorId);
},
getVendorId: function(){
return VendorId;
},
setVendor: function(vendor){
Vendor.push(vendor);
},
getVendor: function(){
return Vendor;
}
};
});
CONTROLLER 1
angular.module('startupApp')
.controller('controller1', function ($scope, Auth, $location, vendorId, $http) {
$scope.user = {};
vendorId.setVendor($scope.user);
vendorId.setVendorId($scope.user.id);
})
CONTROLLER 2
angular.module('startupApp')
.controller('controller2', function ($scope, Auth, $location, vendorId, $http) {
console.log(vendorId.getVendor());//[]
console.log(vendorId.getVendorId());//[]
})
These both end up as empty arrays. To be clear, there is page1.html that has a form that populates the $scope.user object in controller1. I want to be able to get this object on page2.html from the page2.html controller (controller2)
Your code should work, unless controller1 is not invoked before controller2.
run this code snippet and see by yourself.
angular.module("test", [])
.service("vendorId", function () {
var VendorId = [];
var Vendor = [];
return {
setVendorId: function(vendorId){
VendorId.push(vendorId);
},
getVendorId: function(){
return VendorId;
},
setVendor: function(vendor){
Vendor.push(vendor);
},
getVendor: function(){
return Vendor;
}
};
})
.controller("Controller1", function ($rootScope, vendorId) {
this.user = {id : 1};
this.save = function () {
vendorId.setVendor(this.user);
vendorId.setVendorId(this.user.id);
// simulates page change
$rootScope.saved = true;
}
})
.controller("Controller2", function (vendorId) {
this.user = vendorId.getVendor();
this.id = vendorId.getVendorId();
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="test">
<div data-ng-if="!saved" data-ng-controller="Controller1 as scope1">
<input type="text" data-ng-model="scope1.user.name" />
<button data-ng-click="scope1.save()">Save</button>
</div>
<div data-ng-if="saved" data-ng-controller="Controller2 as scope2">
The user : {{scope2.user}} <br />
The user id : {{scope2.id}}
</div>
</div>

Angular js - Using Service

Menu-Controller:
// Left Menu Start
'use strict';
angular.module("MainApp")
.controller('LeftMenuCtrl', function ($scope, $rootScope, actionCall) {
$scope.notify = {};
$scope.actionUrlCall = function(action)
{
actionCall.actionUrlCall(action, function(response){
$scope.notify = actionCall.notify;
console.log($scope.notify);
});
};
});
Now there are several html pages in view:
Each one of them has these notification directives:
<div class="col-sm-12">
<notification type="success"></notification>
<notification type="error"></notification>
<notification type="warning"></notification>
</div>
Which displays the notification as per the output from actionCall service.
I have console logged console.log($scope.notify); and I'm getting the required result. Problem is I don't know how to communicate this with the directives present on various different pages with different controllers and different scope.
Ok, so this is how I finally solved the issue.
I created a new service(menu-service.js) :
'use strict';
angular.module("MainApp")
.factory('menuClick', function($rootScope) {
var sharedService = {};
sharedService.notify = {};
sharedService.prepForBroadcast = function(msg) {
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
Then I injected my service which is named as menuClick in my menu controller and added some lines in it:
angular.module("MainApp")
.controller('LeftMenuCtrl', function ($scope, $rootScope, menuClick) {
$scope.handleMenuClick = function(action) {
menuClick.notify.warningNotify = true;
menuClick.notify.errorNotify = true;
menuClick.notify.successNotify = true;
if(!action.IsEnabled)
{
menuClick.notify.warningNotify = false;
menuClick.notify.warningMessage = "This operation is disabled ( "+action.Text+" )";
menuClick.prepForBroadcast(menuClick.notify);
}
};
});
Then I injected menuClick to the controllers where I needed to listen the Broadcast data and added following lines in those controllers:
$scope.$on('handleBroadcast', function() {
$scope.notify = menuClick.notify;
});
And it started working!!

Resources