I have these controller codes from different js files.
NLGoalsCtrl.js
angular.module('mysite').controller('NLGoalsCtrl', function ($scope) {
$scope.goals_selected = [];
});
NLSessionsCtrl.js
angular.module('mysite').controller('NLSessionsCtrl', function ($scope) {
//access $scope.goals_selected here
});
I need to be able to access the $scope.goals_selected from the NLSessionsCtrl. How do I do this? Thanks guys.
Use a factory/service to store the goals which will be responsible for sharing data among the controllers.
myApp.factory('myService', [function() {
var goals = {};
return {
getGoals: function() {
return goals
},
setGoals: function(op) {
goals = op;
},
}
}])
.controller('NLGoalsCtrl', [function($scope, myService) {
$scope.goals_selected = {};
//Update goals_selected
myService.setGoals($scope.goals_selected );
}])
.controller('NLSessionsCtrl', [function($scope, myService) {
//Fetch
$scope.goals_selected = myService.getGoals();
}]);
$scope is an "object" that "binds" to DOM element where you apply controller. So the context of $scope remains inside the controller.
If you want to access the variables in 2 controllers , try to share it via a service/Factory or $rootScope
Here is a sample App
the one that you want to access in any controller assign it to the $rootScope.
and access it in any controller you want.
Related
I want to be able to determine which directive is displayed based on a variable from a shared service. This is what I have so far.
main.html
<character-select ng-if="stateChangeService.playerState === 'characterSelect'"></character-select>
<fight-display ng-if="stateChangeService.playerState === 'fight'"></fight-display>
service
angular
.module('outerZone')
.service('stateChangeService', stateChangeService);
function stateChangeService() {
var vm = this;
vm.playerState = 'characterSelect';
}
Currently when I load the page, nothing displays. The service is injected into both the character-select directive and the fight-display directive as well as the MainController. Any ideas?
There is no way your view knows anything about your service. You should assign your service to context.
angular.module('outerZone').controller('MainController', MainController)
MainController.$inject = ['stateChangeService'];
function MainController(stateChangeService){
var vm = this;
vm.stateChangeService = stateChangeService;
}
<body ng-controller="MainController as mc">
<character-select ng-if="mc.stateChangeService.playerState === 'characterSelect'"></character-select>
<fight-display ng-if="mc.stateChangeService.playerState === 'fight'"></fight-display>
</body>
View in Angular can access variables in current $scope or parent scopes.
so you have to assign service to current $scope or $rootScope.
(function() {
angular.module('app')
// your service
.service('myService', myServiceFunction);
function myServiceFunction(){
this.data = function(){ return true; };
};
// your controller
.controller('myController', myControllerFunction);
// inject $scope and service
myControllerFunction.$inject=['$scope','myService'];
function myControllerFunction($scope, myService){
//attatch service to current scope
$scope.myService = myService;
};
})();
<div ng-app='app' ng-controller="myController">
{{myService.data()}}
</div>
You can only use those variable on view/HTML which are bounded to $scope or this(while using controllerAs pattern). You should expose your service/factory/constant on view, OR rather better way would write a getter for accessing particular variable from service. Its best practice to expose relevant matter from service. There after you could call that getter from view like getPlayerState()
HTML
<character-select ng-if="getPlayerState() === 'characterSelect'"></character-select>
<fight-display ng-if="getPlayerState() === 'fight'"></fight-display>
Code
app.controller('myCtrl', function(stateChangeService, $scope){
$scope.getPlayerState = function(){
return stateChangeService.playerState;
}
})
I also want to have acces to a $scope in this controller so I can do methods like ng-click and ng-change in my html. I know have this $http but i cant do anny angular function on it and I can't seem to figure out how I can use a $scope in this controller.
app.controller('songController', ['$http', function($http) {
$songs = this;
$songs.tracks = [];
$http({
url: "http://api.q-music.be/1.2/tracks/plays?limit=20",
dataType: "jsonp",
jsonp: "callback"
})
.success(function(lastSongsList) {
$songs.tracks = lastSongsList.played_tracks;
console.log($songs.tracks);
});
}]);
I want to be able to do methods in this controller like this :
$scope.change = function() {
$scope.counter++;
};
You need to inject your scope dependency like this :
app.controller('songController', ['$http', '$scope', function($http, $scope) {
Change your controller definition to this:
app.controller('songController', ['$http', '$scope', function($http, $scope) {
The same way that you inject $http into your controller, you need to do the same with $scope to allow your controller to use it.
Look up dependency injection and you'll find all kinds of stuff about. It's pretty useful and you'll want to understand how it works if you're going to be working with Angular.
$songs = this;
$songs.tracks = [];
should also be
$scope.songs = this;
$scope.songs.tracks = [];
same for the $http success handler
$songs.tracks = lastSongsList.played_tracks;
should be
$scope.songs.tracks = lastSongsList.played_tracks;
Your change function can remain in the controller
$scope.change = function() {
$scope.counter++;
};
Then in your html, e.g. button input use ng-click="change()"
I'd like to do simple notifications in angular. Here is the code I've written.
http://pastebin.com/zYZtntu8
The question is:
Why if I add a new alert in hasAlerts() method it works, but if I add a new alert in NoteController it doesn't. I've tried something with $scope.$watch but it also doesn't work or I've done something wrong.
How can I do that?
Check out this plnkr I made a while back
http://plnkr.co/edit/ABQsAxz1bNi34ehmPRsF?p=preview
I show a couple of ways controllers can use data from services, in particular the first two show how to do it without a watch which is generally a more efficient way to go:
// Code goes here
angular.module("myApp", []).service("MyService", function($q) {
var serviceDef = {};
//It's important that you use an object or an array here a string or other
//primitive type can't be updated with angular.copy and changes to those
//primitives can't be watched.
serviceDef.someServiceData = {
label: 'aValue'
};
serviceDef.doSomething = function() {
var deferred = $q.defer();
angular.copy({
label: 'an updated value'
}, serviceDef.someServiceData);
deferred.resolve(serviceDef.someServiceData);
return deferred.promise;
}
return serviceDef;
}).controller("MyCtrl", function($scope, MyService) {
//Using a data object from the service that has it's properties updated async
$scope.sharedData = MyService.someServiceData;
}).controller("MyCtrl2", function($scope, MyService) {
//Same as above just has a function to modify the value as well
$scope.sharedData = MyService.someServiceData;
$scope.updateValue = function() {
MyService.doSomething();
}
}).controller("MyCtrl3", function($scope, MyService) {
//Shows using a watch to see if the service data has changed during a digest
//if so updates the local scope
$scope.$watch(function(){ return MyService.someServiceData }, function(newVal){
$scope.sharedData = newVal;
})
$scope.updateValue = function() {
MyService.doSomething();
}
}).controller("MyCtrl4", function($scope, MyService) {
//This option relies on the promise returned from the service to update the local
//scope, also since the properties of the object are being updated not the object
//itself this still stays "in sync" with the other controllers and service since
//really they are all referring to the same object.
MyService.doSomething().then(function(newVal) {
$scope.sharedData = newVal;
});
});
The notable thing here I guess is that I use angular.copy to re-use the same object that's created in the service instead of assigning a new object or array to that property. Since it's the same object if you reference that object from your controllers and use it in any data-binding situation (watches or {{}} interpolation in the view) will see the changes to the object.
I'm trying to pass a Javascript object into my AngularJS controller and having no luck.
I've tried passing it into an init function:
<div ng-controller="GalleryController" ng-init="init(JSOBJ)">
And on my controller side:
$scope.init = function(_JSOBJ)
{
$scope.externalObj = _JSOBJ;
console.log("My Object.attribute : " + _JSOBJ.attribute );
};
Though the above doesn't seem to work.
Alternatively, I've tried pulling the attribute from the AngularJS controller that I am interested in for use in an inline <script> tag:
var JSOBJ.parameter = $('[ng-controller="GalleryController"]').scope().attribute ;
console.log("My Object.parameter: " + JSOBJ.attribute );
Can anyone tell me: what is the best practice regarding this?
I don't have the option to rewrite the plain Javascript object as it is part of a 3rd party library.
Let me know if I need to provide further clarification and thanks in advance for any guidance!
-- JohnDoe
Try setting it as a value:
angular.module('MyApp')
.value('JSOBJ', JSOBJ);
Then inject it into your controller:
angular.module('MyApp')
.controller('GalleryController', ['JSOBJ', function (JSOBJ) { ... }]);
Since your object is a part of third-party library you have to wrap it app in something angular.
Your options are:
if it is jquery pluging init'ed for a DOM node etc you can create a directive
example
myApp.directive('myplugin', function myPlanetDirectiveFactory() {
return {
restrict: 'E',
scope: {},
link: function($scope, $element) { $($element).myplugin() }
}
});
if it is something you need to init you can use factory or service
example
myApp.service(function() {
var obj = window.MyLib()
return {
do: function() { obj.do() }
}
})
if it is plain javascript object you can use value
example
myApp.value('planet', { name : 'Pluto' } );
if it is constant ( number, string , etc) you can use constant
example
myApp.constant('planetName', 'Greasy Giant');
Reference to this doc page: https://docs.angularjs.org/guide/providers
Also I strongly encourage you to read answer to this question: "Thinking in AngularJS" if I have a jQuery background?
If you have JSOBJ accessible via global scope (via window), than you can access it through window directly as in plain JavaScript.
<script>
...
window.JSOBJ = {x:1};
...
</script>
Option 1.
<script>
angular.module('app',[]).controller('ctrl', ['$scope', function($scope) {
$scope.someObject = window.JSOBJ;
}]);
</script>
However it makes the controller code not testable. Therefore $window service may be used
Option 2.
<script>
angular.module('app',[]).controller('ctrl', ['$scope', '$window', function($scope, $window) {
$scope.someObject = $window.JSOBJ;
}]);
</script>
If you want to make some abstraction layer to make your controller agnostic for the source from where you get the object, it is recommended to define service which is responsible for fetching value and then inject it to your controllers, directives, etc.
Option 3.
<script>
angular.module('app',[])
.service('myService', function() {
var JSOBJ = ...; // get JSOBJ from anywhere: localStorage, AJAX, window, etc.
this.getObj = function() {
return JSOBJ;
}
})
.controller('ctrl', ['$scope', 'myService', function($scope, myService) {
$scope.someObject = myService.getObj();
}]);
</script>
Besides of it, for simple values you can define constant or value that may be injected to any controller, service, etc.
Option 4.
<script>
angular.module('app',[]).
value('JSOBJ', JSOBJ).
controller('ctrl', ['$scope', 'JSOBJ', function($scope, JSOBJ) {
$scope.someObject = JSOBJ;
}]);
</script>
I am using angular framework and trying to pass $scope to different controller in my app.
UPDATE:
My problem is I wan't obtain the $scope data until user click a button.
.controller('firstCtrl', function($scope) {
$scope.getTest = function(){
$scope.test1 = 'good.'
$scope.test2 = 'bad.'
…..more
}
})
I need to pass $scope object to different controller
.controller('secondCtrl', function($scope) {
console.log($scope.test1)
})
How do I do it? Thanks!
In order to share data between two controllers you need to use factory.
For more details, please watch this video: "AngularJS Video Tutorial: Sharing Data Between Controllers" by John Lindquist.
To share information between controllers, you use services. A service can be created like this:
//Create angular main app module
var app = angular.module('myApp', []);
//create a service
app.service('sharedService', function () {
this.test1 = [1, 2, 3, 4];
});
//one controller, injecting the service
app.controller('firstCtrl', function ($scope, sharedService) {
sharedService.test1[0] = 5;
console.log(sharedService.test1[0]) //5, 2, 3, 1
});
//two controller, injecting the same service
app.controller('secondCtrl', function ($scope, sharedService) {
sharedService.test[1] = 4;
console.log(sharedService.test1[0]) //5, 4, 3, 1
});
Here is an example I just created on jsFiddle:
http://jsfiddle.net/NHtFu/
Use custom events on the $rootScope
.controller('firstCtrl',['$rootScope', function($rootScope) {
$scope.getTest = function(){
$rootScope.your_object = {foo:bar}
$rootScope.$emit('custom_event');
}
}])
.controller('secondCtrl', function($scope,$rootScope) {
$rootScope.$on('custom_event',function(){
//do stuff
//$rootScope.your_object is available
})
});
You may need to unbind the root scope from that event if the controllers instantiate more then once
There may be an objection against 'polluting' the root scope but that's what its there for.