I am trying to get FirstCtrl data in SecondCtrl, but there is no response in SecondCtrl, Please help me to solve this
I Have tried to use $broadcast and $emit on $rootscope. but there is not data coming on $on
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('FirstCtrl', function( $scope, $rootScope) {
$scope.firstName = 'Ganpat';
//$rootScope.$emit('firstName', $scope.firstName);
$rootScope.$broadcast('firstName:broadcast', $scope.firstName);
});
myApp.controller('SecondCtrl', function( $scope, $rootScope){
$rootScope.$on('firstName:broadcast', function(event,data){
$scope.firstName = data;
console.log(data);
});
});
</script>
<body>
<div ng-app="myApp">
<div ng-controller="FirstCtrl">
<input type="text" ng-model="firstName">
<br>Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{firstName}}
</div>
</div>
</body>
</html>
Code now compiles and runs properly. You can cut and past this into fiddler and run.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var myApp = angular.module('myApp', []);
myApp.factory('UserService', function () {
var self = this;
var firstName = '';
self.SetFirstName = function (name) { firstName = name; }
self.GetFirstName = function () { return firstName; }
return self;
});
myApp.controller('FirstCtrl', ['$scope', 'UserService', function ($scope, UserService) {
UserService.SetFirstName("coolMan");
}]);
myApp.controller('SecondCtrl', ['$scope', 'UserService', function ($scope, UserService) {
$scope.firstNameTest = '';
$scope.service = UserService;
$scope.$watch('service.GetFirstName()', function (newVal) {
console.log("New Data", newVal)
$scope.firstNameTest = newVal;
});
}]);
</script>
<body>
<div ng-app="myApp">
<div ng-controller="FirstCtrl">
<input type="text" ng-model="firstName">
<br>
Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{firstNameTest}}
</div>
</div>
</body>
</html>
EDIT
Addressing OPS comment.
I know this method will work and it will give a correct result, but i
have studied the $rootscope and event $emiter and $broadcast will do
this trick, so if you know about that then please tell me, thank you
for your answer.
What you want to do is a bad idea. Your method forces a tighter coupling between controllers. By working on the rootscope you are forcing all controllers to rely on a certain Item being in rootscope. This is bad because controllers are not self contained modules.
By passing around a service you can decouple the controllers. Meaning that they can be used as view controllers, directive controllers, pretty much anything that requires an isolated module.
Also using a service you can now cache the result, perform centralized business logic on it, and encapsulate how you get the data. This cannot be done easily on the rootscope.
To sum it up, I will not show you a terrible way of doing what you want done. It is not good and will let other people whom look at this post use bad practices.
Related
as you can see I have opened .xml file and parsed it to a xmlDoc. What I am trying to achieve is that this xmlDoc will be accessible from the whole script(I want to make some functions later which will be displaying elements from .xml to a screen). I searched the web and find that it is possible via global variable $rootScope but couldn't implement it correctly. I hope you guys can help me. Thanks.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp">
<p id="title">asd</p>
<button name="opt1" ng-click="">YES</button>
<button name="opt2" ng-click="">NO</button>
<script>
var app = angular.module('myApp', []);
var parser, xmlDoc;
app.run(function($rootScope, $http) {
text = $http.get("file.xml").then(function(response) {
return response.data;
}).then(function(text) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"text/xml");
document.getElementById("title").innerHTML =
xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
});
});
</script>
</body>
</html>
There are many ways in angular to declare and use a global variable.
examples:
1. By using $rootScope.
we need to add a dependency in our controller or service like:
app.controller('myCtrl', ['$rootScope', '$scope', function($rootScope, $scope){
$rootScope.yourVar = 'YourValue';
....
....
}]);
and then You can use this `yourVar` variable anywhere in your code.
Another way is by using angular factory or servive.
app.factory('factoryObj', ['$scope', function($scope){
let factoryObj.yourVar = 'yourValue';
return factoryObj;
}]);
Now in any controller or any other service, by using this factoryObj as a dependency and then inside that controller or service we can use factoryObj.yourVar as a variable. as:
app.controller('myCtrl',['$rootScope','$scope','factoryObj'function($rootScope,$scope, factoryObj){
console.log('factoryObj.yourVar value: ',factoryObj.yourVar);
}]);
I am new to Angular js.I have seen the similar question, but I dont understand that.
I have 2 controllers
userControllers.controller('RatingCtrl', function($scope,$http,$rootScope,$route)
userControllers.controller('otherProfileCtrl', function ($scope, $routeParams, $rootScope, $http, $location, $window, $timeout,$uibModal, $compile)
RatingCtrl and otherProfileCtrl, this two modules are inter-related. My need is that, I have reload RatingCtrl from otherProfileCtrl using $route.reload();.Is there is any way to do this without uisng service?plz help
You could pass events from one controller to another in order to achieve this. You would then do something like:
var app = angular.module('myApp', []);
app.controller('firstController', ['$scope', '$rootScope',
function($scope, $rootScope) {
$scope.text = 'Initial text';
$scope.changeText = function(message) {
$scope.text = message;
};
$rootScope.$on('customEvent', function(event, message) {
$scope.changeText(message);
});
}
]);
app.controller('secondController', ['$scope',
function($scope) {
$scope.message = 'Message from second controller';
$scope.sendEvent = function() {
$scope.$emit('customEvent', $scope.message)
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="firstController">
<h2>This is the fist controller:</h2>
<p>{{text}}</p>
</div>
<div ng-controller="secondController">
<h2>This is the second controller:</h2>
<input type="text" ng-model="message" />
<br>
<button ng-click="sendEvent()">Send message</button>
</div>
</div>
Here, the firstController listens to events propagated to the $rootScope, and the secondController sends the message. That is the functionality that you are looking for.
That being said, you would be much better off implementing shared behaviour in a service, since keeping track of all your custom events can be particularly tough.
Hope this helps.
I have a controller with such:
$scope.myVar = 0;
$scope.back = function () {
$scope.myVar--;
};
$scope.next = function () {
$scope.myVar++;
};
If next() (with ngClick) is called 3 times, we get:
//1
//2
//3
but if back() (with ngSwipeLeft) is called it returns
//-1
when I'm obviously expecting
//2
What am I missing here?
update: including ngTouch details - this seems to be the problem.. ngTouch is included.
When I watch the myVar value - its like it exists twice - one with the ngSwipeLeft call, and one with the ngClick call
Your snippet looks fine to me. You need to provide more code, error might be somewhere else. Look at the code below.
<!doctype html>
<html ng-app="myapp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-touch.min.js"></script>
<script>
var app = angular.module('myapp',['ngTouch']);
var controller = app.controller('mycontroller', ['$scope',function($scope){
$scope.myVar = 0;
$scope.back = function () {
$scope.myVar--;
};
$scope.next = function () {
$scope.myVar++;
};
}]);
</script>
</head>
<body ng-controller="mycontroller">
<div>
<h1>MyVar: {{myVar}}!</h1>
<input type="button" value="back" ng-click="back()"/>
<input type="button" value="next" ng-click="next()"/>
</div>
</body>
</html>
Ok, so I've figured out my problem - I wasn't providing enough detail in the question - but if someone runs into something similar in the future, heres what was going on:
I was declaring my controller with ng-controller="myCtrl" in the templates, but also using routing, where I declared my controller like:
$routeProvider.when('/', {
templateUrl: 'myUrl.html',
controller: 'myCtrl'
});
This was instantiating the controller twice, and obviously causing problems (although that seemed to the only one to surface for now).
Removing the controller definition from the routing or the view did the trick.
need to see your html not sure about your problem, here is a sample working code,
<div ng-app="myapp">
<div ng-controller="IncDecController">
<span>current value is {{myVar}}</span>
<img src="https://angularjs.org/img/AngularJS-large.png" ng-swipe-left="back()"></img>
<button ng-click="next()">next</button>
</div>
</div>
script:
angular.module('myapp', ['ngTouch'])
.controller('IncDecController', ['$scope', function ($scope) {
$scope.myVar = 0;
$scope.back = function () {
$scope.myVar--;
};
$scope.next = function () {
$scope.myVar++;
};
}])
I'm having trouble getting a $scope variable to trigger the screen to rebind. Yes, I've tried calling $scope.$apply() after assigning $scope.value = value; Yes, I've tried calling $digest() manually after the assignment; I get the error "$rootScope:inprog] $digest already in progress.
So What I've done is try to get my $rootScope.$on('message'function(){}) listener to create a secondary $broadcast to all scopes to try and get to the bottom of this; however, my $scope's registration of the event is not firing and I'm thinking this might be related to the same issue....maybe not. At any rate, here's my codez.
I'd build a fiddle but it's currently blocked by network policy.
Manifest:
[config]
[index.html]
[foo.html]
[ctrl]
[config] (a couple of attempted hacks. They're marked with comments)
var kata = angular.module('kata',[
'ngRoute'
]).run(['$rootScope',
function($rootScope){
$rootScope.$on('message:foo',function(event,data){
$rootScope.$broadcast('message:bar',['foo1','foo2','foo3']);//send secondary msg
$rootScope.data = data; //Hack #1: When I couldn't get $scope to rebind, I tried to use $rootScope;still doesn't rebind.
});
}]);
kata.config(['$routeProvider',
function($routeProvider){
$routeProvider
.when('/Foo',{
templateUrl: 'foo.html',
controller: 'FooCtrl'
});
}]);
[index] (nothing funny here)
<html ng-app="kata">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"></meta>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="./routingConfig.js"></script>
<script src="./controllers.js"></script>
</head>
<body>
<div class="view-container">
<div ng-view class="view-frame"></div>
</div>
</body>
</html>
[foo.html] (nothing funny here)
A couple of tests with a couple of $scope variables attached to same stuff.
Neither of these update
<div>
This page is for capturing Data
Data: {{data}}
<hr />
<ul>
<li ng-repeat="foo in foos">
<span>Foo Found!</span>
</li>
</ul>
</div>
[ctrl] (created several variables on scope trying to attack this problem in different ways)
var kataCtrl= kata.controller("FooCtrl",
[ '$scope', '$http','$rootScope','$location'
,function($scope, $http, $rootScope , $location) {
$scope.data = "Foo";
$scope.data1 = "[placeholder]";
$scope.foos = [];
//fires, assigns, view does not update
$scope.$watch(function(){
return $rootScope.data;
}, function(){
$scope.foos = ['data','foo','bar','baz'];<=Assignment succeeds. View does not update
$scope.$apply();//<=Does nothing apparent; View does not update
$scope.$digest();//<= Console Error. Already in digest loop
},true);
//does not fire
$scope.$on('message:foo',function(event,data){ //<= This never catches
$scope.data = data;
});
//fires, assigns, View does not update
$rootScope.$on('message:bar',function(event,data){
$scope.foos = ['data','foo','bar','baz'];
$scope.foo1 = data.element1;
$scope.data = "[Foos returned from $rootScope]";
$scope.$apply();//<= Does not help. Changing to $scope.$digest() indicates already in digest loop
});
}]);
So as a recap, $rootScope.$on() inside my config is firing. It is assigning values to variables on $rootScope properly. $rootScope.$broadcast is generating a secondary message. The controller's $scope.$on registration of the message does not catch.The controller's $rootScope.$on registration fires and assigns values on $scope, but the view does not rebind. Calling $scope.$apply() does not help. Calling $scope.$digest() merely reports that a digest loop is currently running.
Scoped variables are assigned to but the view never rebinds.
What in the wide wide world of sports is going on here?
I think the problem is you are broadcasting 'message:bar' and listening to 'message:foo' in controller. I have made simplified version of your code. You can see thet my code emits event to root scope and gots broadcasted event in child scope:
<html ng-app="kata">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"></meta>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
</head>
<body>
<div class="view-container" ng-controller="FooCtrl">
<div class="view-frame">
<div>
This page is for capturing Data
<br>
Data: {{data}}
<hr />
<ul>
<li ng-repeat="foo in foos">
<span>Foo Found!</span>
</li>
</ul>
</div>
</div>
</div>
<script>
var kata = angular.module('kata',[
'ngRoute'
]).run(['$rootScope',
function($rootScope){
$rootScope.$on('message:foo',function(event,data){
$rootScope.$broadcast('message:bar',['Data', 'from', 'root', 'scope']);//send secondary msg
});
}]);
kata.controller("FooCtrl",
[ '$scope', '$http','$rootScope','$location'
,function($scope, $http, $rootScope , $location) {
$scope.data = "Foo";
$scope.data1 = "[placeholder]";
$scope.foos = [];
$scope.$on('message:bar',function(event,data){
$scope.data = data;
});
$scope.$emit('message:foo');
}]);
</script>
</body>
</html>
I'm new to Angular.
I am having problems dealing with variables back and forth between my controller and html.
In my controller not only I want to read $scope, but I also want to use it in a function I have in my services.
This is my factory:
angular.module('myApp.services', [])
.factory('hotels', function($http){
return{
search: function(city, callback){
$http({
method: 'GET',
url: 'http://myhotels.com/hotels/?city='+city+
cache: true
}).success(callback);
}
};
})
controller:
angular.module('myApp.controllers', [])
.controller('SearchHotelsController', ['$scope', 'hotels', function($scope, hotels){
$scope.hotelCity = "";
hotels.search($scope.hotelCity, function(hotelResults){
$scope.hotelResults = hotelResults;
});
}])
and in the html I don't have a button to call the function. It is supposed to be called when I get the scope variable (hotelResults):
<input class="form-control" type="text" ng-model="hotelCity">
<a ng-href="#/searchResults"><button>Search</button></a>
and when it routes to that page, which uses the same controller, I get:
{{hotelResults.name}}
================================================================
I also tried declaring $scope.hotels = {hotelCity: "sf"}; in th controller , then put this in html: <input type="text" ng-model="hotels.hotelCity"> and in my controller to call $scope.hotels.hotelCity in the function, but still they are not connected! no matter what the user puts in the input, I get 'sf' for my hotelCity.
Please someone shed a light on this for me, thanks!
I am also new-bie to angular, and looking at your question, i am not fully aware what you are actually looking for but what i have understood and came up with this. Might help.
<html ng-app="myApp">
<head><title>Test</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
</head>
<body>
<div class="test-wrap" ng-controller="myHotels">
<input type="text" name="h" ng-model="hotelcity" />
<button ng- click="search()">Search</button>
<p>List of Hotel's</p>
<ul>
<li ng-repeat="h in hotel | filter:hotelcity">{{h.name}}</li>
</ul>
</div>
</body>
</html>
<script type="text/javascript">
var myApp = angular.module('myApp',[]);
myApp.controller('myHotels', ['$scope', function($scope) {
$scope.hotel = [{"name":"Test1 hotel"},{"name":"Test2 hotel"},{"name":"Test3 hotel"}];
$scope.search = function(){
console.log($scope.hotelcity);
}
}]);
</script>
I finally decided to pass my data through my url and then get it with $routeParams in my controller.
I didn't figure out the problem with my code, and I kind of expected Angular to be this smooth with passing variables back and forth, but I guess this particular situation is a javascript issue with different scopes and function arguments.
I also learned about the Closure concept of javascript which didn't help me either!
Solution: I put a button at the bottom of the page inside an tag;
<a ng-href="#/searchResults/{{hotelCity}}"><button>Search</button></a>
then in routeProvide in my app.js file:
$routeProvider.when('/searchResults/:city', {templateUrl: 'partials/second.html', controller: 'secondController'});
then in controller:
hotels.search($routeParams.city, function(hotelResults){
$scope.hotelResults = hotelResults;
});
[make sure to declare $routeParams in your controller next to $scope]