I have been using $rootScope to save data in my angular app uptil now, but when user refreshes the page the data is lost. Need to change that.
Login Controller
myapp.controller('loginController', function($scope, $rootScope, loginFactory, requestFactory, userFactory, contactFactory, $location, $cookies) {
$scope.getUser = function(){
delete $rootScope.reqMessage;
var user_repack = {
email: $scope.user.email,
password: $scope.user.password
}
loginFactory.getUser(user_repack, function (data){
$rootScope.users = data
$scope.userData = $cookies.userData || {};
$cookies.userData = data
requestFactory.getRecievedRequests(data, function (data){
if(data.length > 0){
$rootScope.recievedRequests = data;
}
})
contactFactory.getContacts(data, function (data){
$rootScope.userContacts = data;
})
$location.path('/dashboard')
})
}
});
Injecting ngCookies
var myapp = angular.module('demo_app', ['ngRoute', 'ngMessages', 'ngCookies']);
});
Front End
<div ng-controller="userController" ng-show="users">
<div class="pull-right" ng-controller="loginController">
<form>
<input type='submit' value='Logout' ng-click='logout()' class="btn btn-danger">
</form>
</div>
<h5 ng-show="welcome">{{welcome}}</h5>
<h2>Hello {{users.name}} {{userData}}</h2>
I have used both $rootScope and $cookies just to try it out. In the front end users.name prints but not userData.
Been trying to figure this out for a while now. any help is appreciated. Thank you.
PS: Im aware this Q has been asked before, i've read through the other posts but couldn't figure it out.
Edit
have tried following the get & put method from the documentation.
var userCookie = $cookies.get('userCookie')
$cookies.put('userCookie', data);
throws an error saying $cookies.get is not a function
Related
cartController in AngularJS:
angular.module('demo', [])
.controller('Hello', function($scope, $http) {
$scope.refreshCart = function() {
$http.get('http://localhost:8080/rest/cart')
.success(function(response) {
$scope.items = response.data;
});
};
$scope.removeFromCart = function(productId) {
$http.delete('/delete/' + productId)
.success(function (data) {
$scope.refreshCart();
});
};
$scope.addToCart = function(productId) {
$http.put('/add/'+ productId)
.then(function(response) {
$scope.refreshCart();
});
};
});
First HTML file (here everything works):
<a href = "#" type="button" class="btn btn-info" th:attr="
ng-click='addToCart(' + ${product.id} + ')'" data-toggle="modal" data-target="#myModal">
Add to cart</a>
Second HTML file:
<html lang="en" xmlns:th="http://www.thymeleaf.org" ng-app="demo">
<script src="http://localhost:8080/cartController.js"></script>
<body ng-controller="Hello">
(...)
<tbody ng-repeat="item in items.cartItemList">
<div class="row">
<h4 class="nomargin">{{item.product.name}}</h4>
<p>{{item.product.description}}</p>
</div>
<td data-th="Price">{{item.price}} PLN</td>
<td data-th="Quantity">{{item.quantity}}</td>
</tbody>
(...)
So what i need to do is:
1) Hit the button in first HTML file, and load JSON to $scope.items (it works).
2) Show the second HTML file, load JSON from $scope.items, and view this JSON to user.
But when I get the second HTML file and try to show data, the $scope.items is empty. Can you help pleae ?
Do you get console errors in your browser? Maybe you have to define items on the controller as empty array like in the example below ...
.controller('Hello', function($scope, $http) {
//define empty array
$scope.items = [];
$scope.refreshCart = function() {
$http.get('http://localhost:8080/rest/cart')
.success(function(response) {
$scope.items = response.data;
});
};
//...
}
I would suggest you to use broadcast and emit. Pass data between the controllers using these. You should use $broadcast if you want to pass data from parent controller to child controller. And emit if the other way around.
I am using angular 1.x and I am trying to share data from one controller to another
I am using the above model in mainctrl. The radiotmplt.radiohead=='IRU600v3'is from firstctrl. I cannot share data using rootscope. Please advise.
Here is the demo how to share data using RootScope
link Jsfiddle
Js
var app = angular.module('myApp', []);
app.controller('ctrl1', function($scope, $rootScope) {
$scope.data = 'data';
$rootScope.data1 = 'old data';
$scope.setVal = function() {
$rootScope.data1 = 'new data';
}
});
app.controller('ctrl2', function($scope, $rootScope) {
$scope.data = $rootScope.data1;
$scope.$watch('data1', function(o, n) {
$scope.data = $rootScope.data1;
})
});
HTML
<div ng-app='myApp'>
<div ng-controller='ctrl1'>
controller 1
<input type='text' ng-model='data'>
<button ng-click='setVal()'>
Change
</button>
</div>
<hr>
<div ng-controller='ctrl2'>
controller 2
<input type='text' ng-model='data'>
</div>
</div>
Hope this will help you
I have this weird problem that i cant display my scope variable values. I am new with angular but i have done this many times before. So here is main parts of index.html. div-ui is inside of body but it doesn't see here:
<input type="text" class="form-control" ng-model="searchUsers" placeholder="Search users"/>
<a ng-click="search()" ui-sref="search">Search</a>
<div ui-view>
</div>
Here is search.html:
<p>Hello world</p> // Shows normally
<p>{{test1}}</p> // Shows normally
<p>{{test2}}</p> // Nothing
<p ng-repeat="x in searchResult">{{x.username}}</p> // Nothing
<p ng-repeat="(key,value) in searchResult">{{value}}</p> // Nothing
<p ng-repeat="(key,value) in searchResult">{{value.username}}</p> // Nothing
Here is the controller:
(function(){
angular.module('TimeWaste')
.controller('NavigationCtrl', ["$scope", "$http", "$state",
function($scope,$http,$state){
$scope.searchResult = [];
// Tried with and without this
if(localStorage['User-Data']){
$scope.loggedIn = true;
}else{
$scope.loggedIn = false;
}
$scope.logUserIn = function(){
$http.post('api/user/login', $scope.login)
.success(function(response){
localStorage.setItem('User-Data', JSON.stringify(response));
$scope.loggedIn = true;
}).error(function(error){
console.log(error);
});
}
$scope.logOut = function (){
localStorage.clear();
$scope.loggedIn = false;
}
$scope.test1 = "hi";
$scope.search = function (){
$scope.test2 = "hi again";
$http.post("api/user/search", {username: $scope.searchUsers})
.success(function(response){
$scope.searchResult = response;
console.log($scope.searchResult);
// returns array of objects. There is all information that i want.
}).error(function(error){
console.log("ei");
});
}
}]);
}());
Everything looks just normal. Inside of search function it's working and console.log returns just what i except. I have also tried repeat divs and tables but i am pretty sure that it's not the problem here.
Here is also my app.js if the problem is there:
(function(){
angular.module('TimeWaste', ['ui.router', 'ngFileUpload'])
.config(function ($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state("main", {
url: "/",
templateUrl: "app/main/main.html",
controller: "MainCtrl"
})
.state("search", {
url: "/search",
templateUrl: "app/main/search.html",
controller: "NavigationCtrl"
})
});
}());
There is couple more states and they all works just fine. I made it little bit shorter so this post won't be so long.
The reason you're able to see {{test1}} and not other values is because you have 2 different controllers called 'MainCtrl' and 'NavigationCtrl'. You are using ui-sref to switch states. So, this is what happening.
When you click your href link, it looks for search() method inside your MainCtrl and then change the state to "search".
It then loads the variables and methods from NavigationCtrl into scope and that's why you're able to see {{test1}} which is loaded into the scope. But you haven't called search() method and hence you're not able to see the other values.
To check my answer, call your method explicitly inside your controller after your function definition $scope.search();
If you're seeing the result then that is your problem.
OK, at this very point you must add an $scope.$apply or use '.then' instead of 'success' to keep your code according promise pattern.
When you just post, there is a need to force the digest cycle to happen.
$http.post("api/user/search", {username: $scope.searchUsers})
.success(function(response){
$scope.$apply(function() {
$scope.searchResult = response;
});
}).error(function(error){
console.log("ei");
});
I have the Controller
function loginController($scope, $http, $cookieStore, $location) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
$scope.log_me = function() {
$scope.login_me = [];
var login_un = $scope.uservals;
var login_pwd = $scope.passvals;
var logs_me = "api call here";
$http.get(logs_me)
.success(function(response) {
$cookieStore.put('token', response.token);
$cookieStore.put('ex_Id', response.ExId);
$cookieStore.put('Cont_Id', response.contactId);
$cookieStore.put('email', response.email);
$cookieStore.put('name', response.name);
$scope.log_sess = response;
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
if (response.status == "failure, invalid username or password") {
$('.login_error').show();
$('.login_error').html('Invalid username or password');
$('.login_error').delay(4000).fadeOut();
$('.loading').hide();
} else {
$location.path('/dashboard');
}
});
}
}
I have used the above controller in my login page and it is working fine. Now i want to use the same controller in another template and retrieve the value "$scope.sess_id"
My Template is
<div class="page" >
<style>
#report_loader object {
width: 100%;
min-height: 700px;
width:100%;
height:100%;
}
</style>
<div class="loading"> </div>
<section class="panel panel-default" data-ng-controller="loginController">
<div class="panel-body" style=" position: relative;">
<div id="report_loader" style="min-height:600px;">
{{sess_id}}
<script type="text/javascript">
$("#report_loader").html('<object data="https://sampleurl/contact/reports/members/sorted_list.html?ss_id=' + sess_id+' />');
</script>
</div>
</div>
</section>
</div>
I am unable to retrieve the value {{sess_id}} here. What should be done so that i can bring this value in my template
You're routing the user to the "dashboard" route upon successful log in. Even though it might feel like you're using the same "loginController" for both login and dashboard, it will be an entirely new instance of both the controller and $scope. Which is why the {{sess_id}} is not displaying on the dashboard template.
If you're following an MVC-like pattern of AngularJS, ideally you want to be creating a new controller for your dashboard template. See explanation: https://docs.angularjs.org/guide/controller#using-controllers-correctly
So, I would create a DashboardCtrl and share the sess_id between the two. There are plenty of examples out there of how to share data between controllers:
You can use a factory: Share data between AngularJS controllers
You can use $rootScope: How do I use $rootScope in Angular to store variables?
Hope it helps.
I would use the rootScope approach, but an easier way to do that is to simply create a 'global' variable.
In your main controller (not your login controller), define a global scope variable like this:
$scope.global = {};
Then in your login controller, modify your session id to use the global variable:
$scope.global.sess_id= response.ss_id;
alert($scope.global.sess_id);
Then in your html:
<div id="report_loader" style="min-height:600px;">
{{global.sess_id}}
It's simple and works like champ.
I would create a service :
services.sessionService = function(){
var sessionID = null;
this.setSessionID = function(id){
sessionID = id;
}
this.getSessionID = function(){
return sessionID;
}
}
then in your controller :
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
sessionService.setSessionID( $scope.sess_id );
and in your dashboard controller :
$scope.sess_id = sessionService.getSessionID();
Approaches
Your question's answer has many approach. They are:
Using value or service, you can call it wherever your controllers need them.
Using $rootScope, this is very common and easy to use. Just define your $rootScope inside your main controller or whatever controller that called first and then you can call it from other controllers like any $scope behavior.
Using $controller service or usually called controller inheritance. Define this in controller function's parameter, then type $controller('ControllerNameThatIWantToInheritance', {$scope:$scope});
Maybe any other approach can be use to it. Each of them have strength and weakness.
Examples:
using value
.value('MyValue', {
key: null
})
.controller('MyCtrl', function ($scope, MyValue) {
$scope.myValue = MyValue;
})
you can modified MyValue from service too
using $rootScope
.controller('FirstCtrl', function ($scope, $rootScope) {
$rootScope.key = 'Hello world!';
})
.controller('SecondCtrl', function ($scope, $rootScope) {
console.log($rootScope.key);
})
will print 'Hello World', you can also use it in view <div>{{key}}</div>
using $controller
.controller('FirstCtrl', function ($scope) {
$scope.key = 'Hello world!';
})
.controller('SecondCtrl', function ($scope, $controller) {
$controller('FirstCtrl', {$scope:$scope});
})
Second controller will have $scope like first controller.
Conclusion
In your problem, you can split your controller for convenient. But if you dont' want to, try to define $scope.sess_id first. It will tell the Angular that your sess_id is a defined model, and angular will watch them (if you not define it first, it will be 'undefined' and will be ignored).
function loginController($scope, $http, $cookieStore, $location) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
$scope.sess_id = null //<- add this
$scope.log_me = function() {
$scope.login_me = [];
var login_un = $scope.uservals;
var login_pwd = $scope.passvals;
var logs_me = "api call here";
$http.get(logs_me)
.success(function(response) {
$cookieStore.put('token', response.token);
$cookieStore.put('ex_Id', response.ExId);
$cookieStore.put('Cont_Id', response.contactId);
$cookieStore.put('email', response.email);
$cookieStore.put('name', response.name);
$scope.log_sess = response;
$scope.sess_id= response.ss_id;
alert($scope.sess_id);
if (response.status == "failure, invalid username or password") {
$('.login_error').show();
$('.login_error').html('Invalid username or password');
$('.login_error').delay(4000).fadeOut();
$('.loading').hide();
} else {
$location.path('/dashboard');
}
});
}
}
I've built an app with firebase that can login a user and attain their id, but I can't figure out how to incorporate this with a user making a submission of a string.
See Code pen here: http://codepen.io/chriscruz/pen/OPPeLg
HTML Below:
<html ng-app="fluttrApp">
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script src="https://cdn.firebase.com/js/client/2.0.2/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/0.9.0/angularfire.min.js"></script>
</head>
<body ng-controller="fluttrCtrl">
<button ng-click="auth.$authWithOAuthPopup('google')">Login with Google</button>
<li>Welcome, {{user.google.displayName }}</li>
<button ng-click="auth.$unauth()">Logout with Google</button>
<input ng-submit= "UpdateFirebaseWithString()" ng-model="string" ></input>
Javascript Below:
<script>
var app = angular.module("fluttrApp", ["firebase"]);
app.factory("Auth", ["$firebaseAuth", function($firebaseAuth) {
var ref = new Firebase("https://crowdfluttr.firebaseio.com/");
return $firebaseAuth(ref);
}]);
app.controller("fluttrCtrl", ["$scope", "Auth", function($scope, Auth) {
$scope.auth = Auth;
$scope.user = $scope.auth.$getAuth();
$scope.UpdateFirebaseWithString = function () {
url = "https://crowdfluttr.firebaseio.com/ideas"
var ref = new Firebase(url);
var sync = $firebaseAuth(ref);
$scope.ideas = sync.$asArray();
$scope.ideas.$add({
idea: $scope.string,
userId:$scope.user.google.id,
});
};
}])
</script>
</body>
</html>
Also assuming, the above dependencies, the below works to submit an idea, but the question still remains in how to associate this with a user. See codepen here on this: http://codepen.io/chriscruz/pen/raaENR
<body ng-controller="fluttrCtrl">
<form ng-submit="addIdea()">
<input ng-model="title">
</form>
<script>
var app = angular.module("fluttrApp", ["firebase"]);
app.controller("fluttrCtrl", function($scope, $firebase) {
var ref = new Firebase("https://crowdfluttr.firebaseio.com/ideas");
var sync = $firebase(ref);
$scope.ideas = sync.$asArray();
$scope.addIdea = function() {
$scope.ideas.$add(
{
"title": $scope.title,
}
);
$scope.title = '';
};
});
</script>
</body>
There a couple of things tripping you up.
Differences between $firebaseand $firebaseAuth
AngularFire 0.9 is made up of two primary bindings: $firebaseAuth and $firebase. The $firebaseAuth binding is for all things authentication. The $firebase binding is for synchronizing your data from Firebase as either an object or an array.
Inside of UpdateFirebaseWithString you are calling $asArray() on $firebaseAuth. This method belongs on a $firebase binding.
When to call $asArray()
When you call $asArray inside of the UpdateFirebaseWithString function you will create the binding and sync the array each time the function is called. Rather than do that you should create it outside of the function so it's only created one item.
Even better than that, you can abstract creation of the binding and the $asArray function into a factory.
Plunker Demo
app.factory("Ideas", ["$firebase", "Ref", function($firebase, Ref) {
var childRef = Ref.child('ideas');
return $firebase(childRef).$asArray();
}]);
Get the user before the controller invokes
You have the right idea by getting the user from $getAuth. This is a synchronous method, the app will block until the user is returned. Right now you'll need to get the user in each controller. You can make your life easier, by retrieving the user in the app's run function. Inside of the run function we can inject $rootScope and the custom Auth factory and attach the user to $rootScope. This way the user will available to all controllers (unless you override $scope.user inside of your controller).
app.run(["$rootScope", "Auth", function($rootScope, Auth) {
$rootScope.user = Auth.$getAuth();
}]);
This is a decent approach, but as mentioned before $scope.users can be overridden. An even better way would be to resolve to user from the route. There's a great section in AngularFire guide about this.
Associating a user with their data
Now that we have the user before the controller invokes, we can easily associate their id with their input.
app.controller("fluttrCtrl", ["$scope", "Ideas", function($scope, Ideas) {
$scope.ideas = Ideas;
$scope.idea = "";
$scope.UpdateFirebaseWithString = function () {
$scope.ideas.$add({
idea: $scope.idea,
userId: $scope.user.google.id,
}).then(function(ref) {
clearIdea();
});
};
function clearIdea() {
$scope.idea = "";
}
}]);