Angular's Controller doesn't read service value? - angularjs

I already have a code with 2 separate controllers .
Each controller's scope/view has an input text and a span.
All fine.
But Looking at the line with yellow color label(empty at the moment) - which is found within the second controller , I want the value to be the same value from as in first controller .
so I'm expecting the line to be (and changed automatically) :
Value from the FirstController is :First Cntrl
I already know that I need a serivce :
so here is my code :
angular.module('app', [])
.controller("FirstCtrl", ['$rootScope', '$scope', 'myservice', function($rootScope, $scope, myservice)
{
myservice.messageFromCntrl1= this.message;
this.message = "First Cntrl";
}]).controller("SecondCtrl", ['$rootScope', '$scope', 'myservice', function($rootScope, $scope, myservice)
{
this.message = "Second Cntrl";
this.messageFromCntrl1 = myservice.messageFromCntrl1;
}])
.service('myservice', function()
{
this.messageFromCntrl1 = "???";
});
In the first controller I do set
myservice.messageFromCntrl1= this.message;
And in the second controller I do read :
this.messageFromCntrl1 = myservice.messageFromCntrl1;
And in the HTML :
Value from the FirstController is :<span style='color:red;'>{{myservice.messageFromCntrl1}}
But it doesn't work. What am I missing?
JSBIN

I modified your JSBIN, check it here. I believe it behaves now as you want it to.
angular.module('app', [])
.controller("FirstCtrl", ['$rootScope', '$scope', 'myservice', function($rootScope, $scope, myservice)
{
this.message = myservice.messageFromCntrl1;
this.message.data = "First Cntrl";
}]).controller("SecondCtrl", ['$rootScope', '$scope', 'myservice', function($rootScope, $scope, myservice)
{
this.message = "Second Cntrl";
this.messageFromCntrl1 = myservice.messageFromCntrl1;
}])
.service('myservice', function()
{
this.messageFromCntrl1 = {data:""};
});
And in your view
<div ng-controller="FirstCtrl as first">
<input type="text" ng-model="first.message.data">
<h1>{{first.message.data}}</h1>
</div>
<div ng-controller="SecondCtrl as second">
<input type="text" ng-model="second.message">
<h1>{{second.message}} </h1>
Value from the FirstController is:
<span style='color:red;'>{{second.messageFromCntrl1.data}}</span>
</div>
First of all, if you want to keep this value updated between controllers you need to use objects and not simple variables. With objects you operate on references and updates are shared between all references of object.
Second, you tried to access service directly in view. You need to bind service reference to controller's scope.

I've made an edit to your jsbin, tell me if that's what you need
https://jsbin.com/mapuwojocu/1/edit?html,js,output
angular.module('app', [])
.controller("FirstCtrl", ['$rootScope', '$scope', 'myservice',
function ($rootScope, $scope, myservice) {
this.message = "First Cntrl";
this.myservice = myservice;
}
]).controller("SecondCtrl", ['$rootScope', '$scope', 'myservice',
function ($rootScope, $scope, myservice) {
this.message = "Second Cntrl";
this.myservice = myservice;
}
])
.service('myservice', function () {
return {
message: 'Cntrl'
};
});

You can't access service through the view. In addition change all your this to $scope in your controller.
Look at this example:
angular.module('app1', [])
.controller("FirstCtrl", ['$scope', 'myservice', function($scope, myservice)
{
$scope.message = "First Cntrl from code";
myservice.messageFromCntrl1= $scope.message;
}])
.controller("SecondCtrl", ['$scope', 'myservice', function($scope, myservice)
{
$scope.message = "Second Cntrl Code";
$scope.messageFromCntrl1 = myservice.messageFromCntrl1;
}])
.service('myservice', function()
{
this.messageFromCntrl1 = "???";
});

Related

Fire $emit event if model property change

I'm trying to pass some data from child controller to parent controller using $emit + $on .
Here is my code.
angular.module('myApp', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.$emit('EventFromChild',$scope.data.name);
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
}]);
When page is loaded then, Then it successfully passes the data from the child to parent, But when I update the data in child then I also want it to get reflected in parent controller, But it is not emitting the event.
Plunker
It is because you are doing nothing when the child is updated.
You have to use $watch for observing changes. For example, if you want emit changes when data.name changes:
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild',$scope.data.name);
});
Or when any property of data changes:
$scope.$watch('data', function() {
$scope.$emit('EventFromChild',$scope.data);
});
This way the come becomes:
angular.module('app.controllers', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.$emit('EventFromChild',$scope.data.name);
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild', $scope.data.name);
});
}]);
Snippet:
// Code goes here
mc = angular.module('app', [
'app.controllers',
]);
angular.module('app.controllers', [])
.controller('parentCtrl', ['$scope', '$http', '$q', function ($scope, $http, $q) {
$scope.message = 'parent';
$scope.$on('EventFromChild', function (event, data) {
console.log("Event Received");
$scope.message = data;
});
}])
.controller('childCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.data ={"name":"Amit","lastname":"kumar"};
$scope.update = function(){
console.log("Clicked");
$scope.data.name ="Testing";
};
$scope.$watch('data.name', function() {
$scope.$emit('EventFromChild',$scope.data.name);
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<div ng-app="app" ng-controller="parentCtrl">
<b>Parent Event:</b> {{message}}<br />
<br/><br/>
<div ng-controller="childCtrl">
<b>Child Event:</b> {{data.name}}<br />
<input type="button" ng-click="update()" value ="update"/>
</div>
</div>

how to passing data from one controller to another controller using angular js 1

hi all i using angular js i need to transfer the value from one page controller to another page controller and get that value into an a scope anybody help how to do this
code Page1.html
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
$scope.Message="Hi welcome"
}]);
now i want to show scope message into page2 controller
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
///here i want get that scope value
}]);
You can use $rootScope instead of $scope:
// do not forget to inject $rootScope as dependency
$rootScope.Message="Hi welcome";
But the best practice is using a service and share data and use it in any controller you want.
You should define a service and write getter/setter functions on this.
angular.module('app').service('msgService', function () {
var message;
this.setMsg = function (msg) {
message = msg;
};
this.getMsg = function () {
return message;
};
});
Now you should use the setMeg function in Controller1 and getMsg function in Controller2 after injecting the dependency like this.
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
$scope.Message="Hi welcome"
msgService.setMsg($scope.Message);
}]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
///here i want get that scope value
console.log('message from contoller 1 is : ', msgService.getMsg());
}]);
You should use services for it .
Services
app.factory('myService', function() {
var message= [];
return {
set: set,
get: get
}
function set(mes) {
message.push(mes)
}
function get() {
return message;
}
});
And in ctrl
ctrl1
$scope.message1= 'Hi';
myService.set($scope.message1);
ctrl2
var message = myService.get()
Sharing data from one controller to another using service
We can create a service to set and get the data between the controllers and then inject that service in the controller function where we want to use it.
Service :
app.service('setGetData', function() {
var data = '';
getData: function() { return data; },
setData: function(requestData) { data = requestData; }
});
Controllers :
app.controller('Controller1', ['setGetData',function(setGetData) {
// To set the data from the one controller
$scope.Message="Hi welcome";
setGetData.setData($scope.Message);
}]);
app.controller('Controller2', ['setGetData',function(setGetData) {
// To get the data from the another controller
var res = setGetData.getData();
console.log(res); // Hi welcome
}]);
Here, we can see that Controller1 is used for setting the data and Controller2 is used for getting the data. So, we can share the data from one controller to another controller like this.

service is not working in a simple controller

I have this js code
var app = angular.module('app', []);
app.service('testService', function(){
this.sayHello= function(text){
return "Service says \"Hello " + text + "\"";
};
this.sayGoodbye = function(text){
return "Service says \"Goodbye " + text + "\"";
};
});
app.controller('AboutCtrl', ['testService', function ($scope, $location, $http) {
$scope.fromService = testService.sayHello("World");
$scope.toService = testService.sayGoodbye("World");
}]);
and in my html I have this
....
...
hi {{fromService}}
....
...
There are no errors in console and the page is just blank.
Please take a look at AngularJs Docs "Using Dependency Injection".
The correct way:
app.controller('AboutCtrl', ['$scope', '$location', '$http',
'testService', function ($scope, $location, $http, testService) {
$scope.fromService = testService.sayHello("World");
$scope.toService = testService.sayGoodbye("World");
}]);
You can inject your service to controller by these ways.
Inline Array Annotation
app.controller('MyController', ['$scope', 'testService', function($scope, testService) {
// ...Code here
}]);
$inject Property Annotation
var MyController = function($scope, testService) {
// ...
}
MyController.$inject = ['$scope', 'testService'];
app.controller('MyController', MyController);
Implicit Annotation
app.controller('MyController', function($scope, testService) {
// ...
});
if you want to know which one is preferred then read this Dependency Injection
You're not injecting your service properly.
app.controller('AboutCtrl', ['$scope', '$location', '$http',
'testService', function ($scope, $location, $http, testService) {
$scope.fromService = testService.sayHello("World");
$scope.toService = testService.sayGoodbye("World");
}]);
Also in your HTML you should add ng-app="app" and ng-controller to especify your controller.
<!DOCTYPE html>
<html ng-app="app">
<head></head>
<body ng-controller="AboutCtrl">
<p>Hi {{fromService}}</p>
<!-- Also place here your JS files.-->>
</body>
</html>
Supper easy, Actually you are injecting service wrong place check this:
app.controller('aboutCtrl', function ($scope, $location, $http, testService) {
$scope.fromService = testService.sayHello("World");
$scope.toService = testService.sayGoodbye("World");
});

Parent's controller method called in child

I want to get $scope variable value from "inherited" controller. It works for non-scope var but for scope var prints undefined.
appControllers.controller('parentCtrl', ['$scope', '$rootScope', '$http', '$location', '$log',
function ($scope, $rootScope, $http, $location, $log) {
$scope.someVariable = "Scope hello world.";
$scope.getLocalVariable = function (){
return "hello world";
}
$scope.getScopeVariable = function (){
return $scope.someVariable;
}
}]);
appControllers.controller('childCtrl', ['$scope', '$rootScope', '$http', '$location', '$log',
function ($scope, $rootScope, $http, $location, $log) {
$log.debug($scope.getLocalVariable()); // this WORKS
$log.debug($scope.getScopeVariable()); // this DOES NOT WORKS - prints undefined
}]);
part of .html file
<div ng-controller="parentCtrl">
<div ng-controller="childCtrl">
</div>
</div>
Do you have any idea? I also tried
var app = angular.module('angularjs-starter', []);
app.controller('ParentCtrl ', function($scope) {
// I'm the sibling, but want to act as parent
});
app.controller('ChildCtrl', function($scope, $controller) {
var ctrl = $controller('ParentCtrl', {$scope: $scope});
ctrl.methodCall() // DOES NOT WORK
});
But it did not helped. Thanks

AngularJS $injector.invoke - ParentController is not defined

I have 2 controllers defined:
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
}]);
myApp.controller('ChildController', ['$scope', '$injector', function($scope, $injector) {
$injector.invoke(ParentController, this, {$scope: $scope});
}]);
This gives: ReferenceError: ParentController is not defined.
This code works only if ParentController is defined as:
function ParentController($scope) {}
I am trying to inject the parent in the child as then I can inherit the common functions defined in the parent.
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}]);
myApp.controller('ChildController', ['$scope', '$injector', '$ParentController', function($scope, $injector, $ParentController) {
$injector.invoke(ParentController, this, {$scope: $scope});
$scope.name = 'Child';
}]);
myApp.controller('ParentController', ['$scope', function($scope) {
}]);
myApp.controller('ChildController', ['$scope', 'ParentController', function($scope, ParentController) {
// ok now you have ParentController
}]);
But I think you need to use Services to share data/functions between Controllers or using PubSub model:
What's the correct way to communicate between controllers in AngularJS?
This reduces coupling between parts of your app.
This is a basic workaround to achieve what you're after:
var myApp = angular.module('nestedControllersModule',[]);
myApp.factory('ParentControllerFactory', function () {
function ParentControllerFactory($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}
return (ParentControllerFactory);
})
.controller('ParentController', ['$scope', '$injector', 'ParentControllerFactory', function ($scope, $injector, ParentControllerFactory) {
$injector.invoke(ParentControllerFactory, this, {
$scope: $scope
});
}])
.controller('ChildController', ['$scope', '$injector', 'ParentControllerFactory', function ($scope, $injector, ParentControllerFactory) {
$injector.invoke(ParentControllerFactory, this, {
$scope: $scope
});
}]);
I say workaround because it's probably worthwhile looking into properly implementing a service to manage any commonality as previously mentioned (or better yet, splitting commonality into directives, clickme for example is a good candidate)
...also note that $injector.invoke(ParentControllerFactory as it is above will most likely chuck a hissy fit if/when you minify your scripts later on, so be careful where and how it used.
Consider using the Mixin pattern possible by using the $controller service.
In your example, you would replace the $injector service with the $controller service:
var myApp = angular.module('nestedControllersModule',[]);
myApp.controller('ParentController', ['$scope', function($scope) {
$scope.name = 'ParentName';
$scope.Type = 'ParentType';
$scope.clickme = function() {
alert('This is parent controller "ParentController" calling');
}
}]);
myApp.controller('ChildController', ['$scope', '$controller', '$ParentController', function($scope, $controller, $ParentController) {
$controller('ParentController',{$scope: $scope})
$scope.name = 'Child';
}]);
This is a good overview of using the $controller service:
http://vadimpopa.com/split-large-angularjs-controllers-using-the-mixin-pattern/

Resources