I have the following instruction in a file called loginCtrl.js and I cannot make $rootScope to hold the value of vm.userEmail.
app.controller('LoginCtrl', function($timeout, $q, $log, $rootScope /*$auth*/, $location, $mdToast) {
var vm = this;
vm.loginMessage = '';
vm.login = function(){
$auth.login({
$rootScope: vm.userEmail,
password: vm.userPassword
})
}
});
$rootScope would help me in this conditional whenever this particular user gets connected.
if ($rootScope == 'y_y#hotmail.com') {
data = [1,2,3,4]
} else {
data = [5,6,7,8]
}
Any ideas, suggestions or corrections are welcome ;)
$rootscope is like an application context. So you can add new value to the application context. Below is your working code.
app.controller('LoginCtrl', function($timeout, $q, $log, $rootScope /$auth/, $location, $mdToast)
{
var vm = this;
vm.loginMessage = '';
vm.login = function(){
$auth.login({
$rootScope.userEmail : vm.userEmail,
password: vm.userPassword
})
}
});
Now you can use read $rootScope.userEmail from anywhere in the application.
if ($rootScope.userEmail == 'y_y#hotmail.com')
{
data = [1,2,3,4]
} else {
data = [5,6,7,8]`enter code here`
}
instead of
$rootScope = someValue;
use
$rootScope.someValue= someValue;
For second part your code try:
you should watch change on $rootSchope.someValue
something like:
$rootScope.$watch('$rootScope.someValue', function(newValue) {
if (newValue='y_y#hotmail.com') {
data = [1,2,3,4]
}
});
Related
I have the next 'problem' with Angular 1.
I have this Factory that I use to get the data for the current logged user:
angular.module('myModule')
.factory('authFactory', function ($http, $rootScope, Session, api, backend_url) {
var authFactory = this;
var user = {};
authFactory.init = function(){
// This API returns the information of the current user
api.current_user.get({}).$promise.then(function(res){
user = res;
});
}
// I use this function to return the user
authFactory.user = function () {
return user;
};
}
This is a basic Controller example where I'm trying to access the information retrieved by the above factory:
angular.module('myModule.mypage')
.controller('PageCtrl', function ($scope, authFactory) {
$scope.user = authFactory.user();
authFactory.init();
angular.element(document).ready(function () {
// This will return {} because it's called
// before the factory updates user value
console.log(authFactory.user());
console.log($scope.user);
});
});
The problem is that $scope.user = myFactory.user(); is not being updated once the Factory retrieve the user value.
I think my issue is related with myFactory.user();. I'm using a function, so the value returned by the function is not updated after myFactory.user has changed, I think that's why on PageCtrl the variable $scope.user is not getting any value.
My questions are:
Which is the best approach on my controller to wait until the user info is loaded by authFactory ?
Should I use a service instead ?
Problem with your implementation is that user is being initialized when authFactory.init() is invoked using presumably asynchronous API.
I would suggest you to return promise from authFactory.user method.
angular.module('myModule')
.factory('authFactory', function ($http, $rootScope, Session, api, $q, backend_url) {
var authFactory = this;
var user = {};
authFactory.init = function () {
// This API returns the information of the current user
return api.current_user.get({}).$promise.then(function (res) {
user = res;
});
}
//Return promise from the method
authFactory.user = function () {
var deferred = $q.defer();
if (angular.isDefined(user)) {
deferred.resolve(user);
} else {
authFactory.init().then(function () {
deferred.resolve(user);
});
}
return deferred.promise;
};
});
Then modify controller
angular.module('myModule.mypage')
.controller('PageCtrl', function ($scope, authFactory) {
authFactory.user().then(function (user) {
$scope.user = user;
})
});
angular.module('myModule')
.factory('authFactory', function ($http, $rootScope, Session, api, backend_url) {
var authFactory = this;
authFactory.user = {}
// I use this function to return the user
authFactory.getUser() = function () {
return api.current_user.get({}).$promise.then(function(res){
authFactory.user = res;
});
};
}
angular.module('myModule.mypage')
.controller('PageCtrl', function ($scope, authFactory) {
authFactory.getUser().then(function() {
$scope.user = authFactory.user;
});
});
Provide us a JSFiddle, I tried to help you without any testing environment.
I am not able to bind a function declared in the service to a controller. I am basically trying to bind the onChange function in service to onChange function in the controller $scope.
I am getting this error:
angular.js:13424 TypeError: Cannot set property 'onChange' of undefined
Here is my service
app.service('myService', function($http, $rootScope) {
this.selected = {
item: ''
}
this.getData = function(key){
return $http.get('/myapp/stocklist/AMZN');
}
this.gs = [];
var sr = [];
this.siri=[];
var vm=this;
this.cleanData = function(response){
for( var i=0; i<response.data.length; i++ ) {
vm.gs.push(response.data[i].name);
sr.push(response.data[i].high);
}
vm.siri.push(sr);
}
this.onChange = function(key){
vm.getData(key).then(function(response){
vm.cleanData(response);
console.log(vm.siri);
});
}
});
And controller:
app.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.selected = myService.selected;
$http.get('/myapp/stocknames').
$scope.onChange = myService.onChange(); // why is this giving error? how do I do it?
success(function(data) {
$scope.names=data;
console.log($scope.names);
});
}]);
Can you please help
Just a correction to Ahmed's answer. You need to refer the service method as a reference and not the result of executing it. So the code above needs to be updated as:
app.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.selected = myService.selected;
$scope.onChange = myService.onChange;
$http.get('/myapp/stocknames').
success(function(data) {
$scope.names=data;
console.log($scope.names);
});
}]);
I think you just put the $scope.onChange = myService.onChange(); in the wrong place, try:
app.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.selected = myService.selected;
$scope.onChange = myService.onChange();
$http.get('/myapp/stocknames').
success(function(data) {
$scope.names=data;
console.log($scope.names);
});
}]);
After Ahmed answer,
If you want to bind to the function and not to the result of the function,
you have to set to function and not to his result.
In your case:
$scope.onChange = myService.onChange;
and not:
$scope.onChange = myService.onChange();
This is the error
$http.get('/myapp/stocknames').
$scope.onChange = myService.onChange();
There is a dot . after the
$http.get('/myapp/stocknames')
replace that with semicolon because javascript understand that in this way
$http.get('/myapp/stocknames').$scope.onChange = myService.onChange();
Thanks
I have two controllers
app.controller('TestCtrl1', ['$scope', function ($scope) {
$scope.save = function () {
console.log("TestCtrl1 - myMethod");
}
}]);
app.controller('TestCtrl2', ['$scope', function ($scope) {
$scope.var1 = 'test1'
$scope.save = function () {
console.log("TestCtrl1 - myMethod");
}
}]);
Then i have two services
.service('Service1', function($q) {
return {
save: function(obj) {
}
}
})
.service('Service2', function($q) {
return {
save: function(obj) {
}
}
})
For my 60% of stuff i just call save on ctrl1 which then called service save method
Now There are cases where before saving i need to do some stuff like chnaging some object parameters different than genral case there i check e,g
if(model == 'User'){
//Here i do this (sample of code)
var service = $injector.get('Service2');
service.save()
Now my problem is in Service 2 i need access to var1. How can i do that
Use the service(s) itself to share the variable as part of the service object as well as methods of each service
.service('Service2', function($q) {
var self = this;
this.var1 = 'test1';
this.save = function(obj) {
}
});
app.controller('TestCtrl2', ['$scope','Service1','Service2', function ($scope, Service1, Service2, ) {
// bind scope variable to service property
$scope.var1 = Service2.var1;
// add a service method to scope
$scope.save = Service1.save;
// now call that service method
$scope.save( $scope.var1 );
}]);
You can also inject a service into another service if needed
injecting services into other services (one possible method) :
html:
<div id="div1" ng-app="myApp" ng-controller="MyCtrl">
<!--to confirm that the services are working-->
<p>service three: {{serviceThree}}</p>
</div>
js:
angular.module('myApp',[])
.service('s1', function() {
this.value = 3;
})
.service('s2', function() {
this.value = 10;
})
.service('s3', function(s1,s2) { //other services as dependencies
this.value = s1.value+s2.value; //13
})
.controller('MyCtrl', function($scope, $injector) { //$injector is a dependency
$scope.serviceThree = $injector.get('s3').value; //using the injector
});
here's the fiddle: https://jsfiddle.net/ueo9ck8r/
Normally, I created a controller which used $scope syntax, so, I could pass a current $scope to a isolated scope of the modal directive as following:
$scope.openEditModal = function() {
$scope.modalInstance = $modal.open({
templateUrl: 'views/budgets/mainbudgets/edit',
scope: $scope // Passing a $scope variable
});
$scope.modalInstance.close();
};
However, I just switched the controller to use this syntax:
var self = this;
// User edit modal
this.openEditModal = function() {
self.modalInstance = $modal.open({
templateUrl: 'views/budgets/mainbudgets/edit',
scope: self; // This doesn't work
});
self.modalInstance.close();
};
So, how can I pass a current this to be used in isolated scope of the modal directive?
EDIT
Here is the whole code of my controller:
angular.module('sms.budgets').controller('BudgetsMainController', ['$scope', 'Global', '$modal', '$timeout', '$rootScope','Budgets', function($scope, Global, $modal, $timeout, $rootScope,Budgets) {
var self = this;
this.newBudget = {};
this.budgets = [];
function init() {
var data = {};
// Load main budget from DB
Budgets.load('main-budgets').success(function(budgets) {
self.budgets = budgets || [];
});
}
init();
/**
* Create a new main budget
*/
this.create = function() {
var data = {};
data.budget = self.newBudget;
data.dbName = 'Budget';
Budgets.create('budgets', data).success(function() {
self.isSuccess = true;
$timeout(function() {
self.isSuccess = false;
}, 5000);
}).error(function(err) {
self.isError = true;
$timeout(function() {
self.isError = false;
}, 5000);
});
};
this.edit = function() {
self.modalInstance.close();
};
// User edit modal
this.openEditModal = function() {
var newScope = $rootScope.$new();
newScope.modalInstance = self.modalInstance;
newScope.edit = self.edit;
self.modalInstance = $modal.open({
templateUrl: 'views/budgets/mainbudgets/edit',
scope: newScope
});
self.modalInstance.close();
};
this.cancelEditModal = function() {
self.modalInstance.dismiss('cancel');
};
}]);
You can't use this as a scope. They are different. Since $scope is a internal variable of AngularJS you have to keep it as it.
To show that, I've created a Plunkr (open the console and see the diffence between this and $scope)
http://plnkr.co/edit/DkWQk4?p=preview
Anyway, is a good practise to use a different scope on the modal controller. Here you have an example showing how to communicate between the main controller and the modal controller:
From the MainCtrl:
var modalInstance = $modal.open({
templateUrl: 'views/parts/modalUrlImg.html',
controller: 'ModalUrlCtrl',
resolve: {
url: function () { // pass the url to the modal controller
return $scope.imageUrl;
}
}
});
// when the modal is closed, get the url param
modalInstance.result.then(function (url) {
$scope.courses[i].imageUrl = url;
});
From the Modal Ctrl:
.controller('ModalUrlCtrl', function($scope, $modalInstance, url) {
$scope.url = url; // get the url from the params
$scope.Save = function () {
$modalInstance.close($scope.url);
};
$scope.Cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.Clean = function () {
$scope.url = '';
};
});
Hope this help you, cheers.
--- EDIT ---
You can keep the controller as syntax. In fact, you must mix both syntax, since you can only use this to add vars and functions, but not tu access other scope things, such as $scope.$on...
So, to do that in your case, just pass $scope:
var self = this;
// User edit modal
this.openEditModal = function() {
self.modalInstance = $modal.open({
templateUrl: 'views/budgets/mainbudgets/edit',
scope: $scope;
});
self.modalInstance.close();
};
I've tried in the updated plunkr and it's working now:
http://plnkr.co/edit/DkWQk4?p=preview
$scope != controller
By passing this to $modal.open() you are passing the reference of the controller and not the scope. Try passing $scope instead.
I have the following code:
appModule = angular.module('appModule', []);
appModule.factory('sharedApplication', function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
});
This code works perfectly and as expected until I try to minify my javascript and then I get
Error: Unknown provider: eProvider <- e
This is because the $http argument in my factory function has been renamed to 'e' for minification purposes. So how can I manually inform the appModule what to inject by name to avoid minification breaking my code?
Thanks in advance.
Try
appModule.factory('sharedApplication', ['$rootScope','$http',function($rootScope, $http) {
}]);
regards
ng-annotate is also a good library so that the required dependency is injected automatically. You should check it out.
Code sample:
/* ngInject */
appModule.factory('sharedApplication', function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
});
Then you don't have to write:
appModule.factory('sharedApplication', ['$rootScope','$http',
function($rootScope, $http) {
var sharedApp;
sharedApp = {};
sharedApp.currentView = "home-section";
sharedApp.pastEvents = null;
$http.get('api/highlights').success(function(response) {
return sharedApp.pastEvents = response.data;
});
return sharedApp;
}]);
The more elegant and easier to read approach:
appModule.factory('myFactory', myFactory);
myFactory.$inject = ['$rootScope','$http'];
function myFactory($rootScope, $http) {
...
}