AngularJS show login/logout in menu based on user status - angularjs

I am making a simple angularJS application and pretty new to it. I have a menu like this
home login
I want the login to change to logout if the user has successfully loggin in. I have implemented the login (psuedo implenation), the probem I am facing is, my menu is at the top out out '
I looked at this question AngularJs, change menu item whether user is connected or not but I could not get my problem solved with it.
How do I fix this? My controller for home looks like this
scotchApp.controller('mainController', function($scope, user) {
// create a message to display in our view
$scope.isUserLoggedIn = user.getSession();
$scope.message = 'Everyone come and see how good I look!' + user.getSession();
$scope.submit = function(){
alert('Thank you. Request is sent successfully');
$('#SupportModal').modal('hide');
};
});
where user is FactoryService. That part is working fine. Any help is appreciated.
If I show {{isUserLoggedIn}} value next to menu it always show false, which is the problem. But if I put that in home.html, it show correct value. The problem is I can't build the logic with {{isUserLoggedIn}} in the menu.

I would recommend you to use ui-router.
It provide nested views and will help you a lot with this issue.
Here is a quick example(in plunker) of how to use it in your case (really simplified) :
Here is how your states should look :
$stateProvider
.state('app', {
templateUrl: 'head.html',
controller: 'HeadCtrl',
})
.state('app.feature1', {
url:'/feature1',
templateUrl: 'feature1.html',
controller:'FeatureCtrl'
})
And your differents HTML files :
Index.html (just showing the body part) :
<body ng-app="testApp">
<ui-view></ui-view>
</body>
Head.html :
<div>
<div class="header">
You are currently <span ng-show="user.connected">connected</span><span ng-show="!user.connected">disconnected</span>
</div>
<ui-view></ui-view>
</div>
feature1.html
<div class="page">
<div>
I am Bill <button ng-click="connect()">Connect as Bill</button>
</div>
<div>
I am Steve <button ng-click="connect(1)">Connect as Steve</button>
</div>
<div>
<button ng-click="disconnect()">Disconnect</button>
</div>
</div>
What you need to understand is that if you reach the "/feature1" url, you will be in state app and its substate feature1 (state app.feature1)
The first ui-view will be filed by app state's template. The ui-view in the template will be filed by feature1 state's template.
I know this is a bit unclear, but try to follow a "gettting started" guide and this exemple should help you a lot.
Hope it helped

Related

ng-view for multiple form load in single page application

I am trying to load different form based on user interaction in single page application. ng-view was helpful until i had to load/hide forms in different divs of same page.
div#1: it will have catalog names populated from ng-repeat.
div#2: should populate forms ( order / schedule / list ) based on button click from top nav.
div#3: should only populate sub catalog list when user selects catalog in div#1.
index.html
<div class="left_column">
<ul>
<li ng-repeat="catalog in catalogs">{{ catalog }}</li>
</ul>
</div>
<div class="top_row">
<ng-view></ng-view>
</div>
<div class="bottom_row">
<ng-view></ng-view>
</div>
app.js
myApp.config(function($routeProvider){
$routeProvider
.when('/orderForm', {
templateUrl: '/orderForm.html',
controller: 'orderFormController'
})
.when('/scheduleForm', {
templateUrl: '/views/html/parameterForm.html',
controller: 'parameterFormController'
})
.when('/subCataloglist', {
templateUrl: '/subCataloglist.html',
controller: 'subController'
})
});
How can i load different forms at a time in single page ? is there any better example for multi view logic ?
I think that this attempt isn't correct.
I have seen only one ng-view, which could change class attached according to view url.
But here i propose much simpler architecture.
Use one view. On this view do ng-repeat in div1 as it was.
in div2 do a ng-if statement and connect it with clicking on buttons.
div three simillar - you can use ng-show or ng-if. ng-if doesn't render in dom, ng-show renders but hide.
<div class="top_row">
<form id="form1" ng-if="selval=1">
</form>
<form id="form2" ng-if="selval=2">
</form>
</div>
menu:
<ul>
<li>order</li>
<li>schedule</li>
controller attached to current html view:
$scope.sel = function(n){
$scope.selval = n;
}
As two-way binding is implemented in angular, it will work automatically.

How to prevent losing data when moving from one state to another in multi-step form?

I am new to web programming and especially to AngularJS.
So maybe my question will seem naive to some of you.
I'm developing a single page application using angular-ui-router.
I have created a multi-step form that contains 3 states:
(function () {
"use strict";
angular.module("sensorManagement", ["ui.router", "ngAnimate", "ngResource", "toaster"])
.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterPorvider) {
$urlRouterPorvider.otherwise("/Sensor/Home");
$stateProvider
.state("MultiStepForm", {
url: "/Sensor/MuiltyStepForm",
templateUrl: "/app/MultiStepForm/MuiltyStepForm.html",
})
.state('MultiStepForm.step1', {
url: '/step1',
templateUrl: '/app/MultiStepForm/FormStep1.html'
})
.state('MultiStepForm.step2', {
url: '/step2',
templateUrl: '/app/MultiStepForm/FormStep2.html'
})
.state('MultiStepForm.step3', {
url: '/step3',
templateUrl: '/app/MultiStepForm/FormStep3.html'
});
}]);
})();
Here is the HTML code:
<!-- form.html -->
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div id="form-multiple-step">
<div class="page-header text-center">
<!-- the links to our nested states using relative paths -->
<!-- add the active class if the state matches our ui-sref -->
<div id="status-buttons" class="text-center">
<a ui-sref-active="active" ui-sref=".step1"><span>STEP1</span></a>
<a ui-sref-active="active" ui-sref=".step2"><span>STEP2</span></a>
<a ui-sref-active="active" ui-sref=".step3"><span>STEP3</span></a>
</div>
</div>
<form id="single-form">
<!-- our nested state views will be injected here -->
<div id="form-views" ui-view></div>
</form>
</div>
</div>
</div>
As you can see I have 3 states and each state has it's own view. The views have multiple elements (textboxes and checkboxes).
When the user enters some data for the STEP1 view and moves to the next step (STEP2 or STEP3) then at some point goes back to STEP1 all data is deleted. I checked with fiddler and can see that when I move from one state to another a call is made to the server and a new view generated.
My question is how can I prevent the lose of data when I move from one state to another? Do I have to use caching? Or maybe there is another way to prevent server calls and keep the data alive until the submit button clicked.
When you feel you have to save data across your controllers in your app. you should use a service.
app.factory('sharedDataService', function ($rootScope) {
console.log('sharedDataService service loaded.');
// do something here that can be shared in other controller
});
//pass this service in your controller to use it there
app.controller('Controller2', ['$scope', 'sharedDataService', function ($scope, sharedData) {
console.log('Controller2 controller loaded.');
//get data from shared service
}]);
find a useful Fiddle here
Cheers if it helps!
I think what you need to do is share you $scope between the parent and child stats. here is the stackoverflow post with good example. https://stackoverflow.com/a/27699798/284225

AngularJs one page app ng-view trouble

I am brand new to AngularJs and after following some tutorials I decided to try to implement a one page app into one of my projects. I have it working but I had one question about this code. Could I change what is shown on the first page before they navigate to anything? I don't want it shown on every page just when they first land on it before clicking any links.
var app=angular.module('single-page-app',['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/',{
templateUrl: 'home.html'
})
.when('/about',{
templateUrl: 'about.html'
});
});
app.controller('cfgController',function($scope){
/*
Here you can handle controller for specific route as well.
*/
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="single-page-app">
<div ng-controller="cfgController">
<div>
<nav>
<ul>
<li>Home</li>
<li>About us</li>
</ul>
</nav>
</div>
<br/>
<div ng-view>
<!--
This DIV loads templates depending upon route.
-->
</div>
</div>
</body>
The pages load fine and if I try to add something to the index.html under ng-view it doesn't show up on the page.
You want to put the content to show up when a user first hits your site under in your "home.html" page which is linked to your "/" route for "ng-view". When a user clicks a link, they will be taken to a new route, and the code/ will be replaced by the route they selected.

How to do an angularjs multi-step/wizard form on one page/url

I'm trying to figure out reasonable approaches in AngularJS for creating a function that is composed of multiple steps (i.e., a wizard) but is linked to one page/URL. The data from one step would have to send data to (or share data with) the next step.
The main points are:
the url should remain the same (i.e., http://mydomain/myapp/nameupdater) for all of the steps and,
the data can be sent amongst steps (i.e., I have to give the data found from step 1 to populate the data in step 2).
For example, suppose that I have a function that does a bulk update of names:
In step 1 the function makes you search for a name.
In step 2 the function presents a list of names that were found from step 1 and allows the user to edit them.
I started an approach where each step had its own view and controller. And, the angular-ui-router maintained the states of the function. But, I have no idea how I would share the data between the steps.
Does anyone know of a good approach to establishing multi-step/wizard forms in angularjs?
My Plunker code is here of my very weak attempt at this.
I think the best way of doing this would be to use ng-switch, just one controller, one route, no reload, using variables shared in all steps, like this:
<div ng-controller="stepCtrl">
<div ng-switch="step">
<div ng-switch-when="1">
<!-- here you can include your step 1 template,
or simply just hardcode it here: -->
<div ng-include src="'.../step1.html'">
<button ng-click="setStep(1)"></button>
</div>
<div ng-switch-when="2">
<div ng-include src="'.../step2.html'">
<button ng-click="setStep(2)"></button>
</div>
<div ng-switch-when="3">
<div ng-include src="'.../step3.html'">
<button ng-click="setStep(3)"></button>
</div>
</div>
</div>
yourApp.controller('stepCtrl',function($scope){
$scope.step = 1;
$scope.setStep = function(step){
$scope.step = step;
}
});
This way you can also manipulate the URL to add a step at the end of your current location.
UPDATE :
Actually this answer is for long time ago , this days I personally prefer to use ui-router which is a great module which you can inject to your AngularJs application and make it even more cool with nested views .
Speaking of nested views , bellow is my new approach for a multystep form with some animation :
First :
Using $stateProvider declare any steps you want in separate views :
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('wizard', {// this will be the wrapper for our wizard
url: '/wizard',
templateUrl: 'wizard.html',
controller: 'wizardController'
})
.state('wizard.stepOne', {// this will be the wrapper for our wizard
url: '/stepOne',
templateUrl: 'stepOne.html',
controller: 'wizardController'
})
.state('wizard.stepTwo', {// this will be the wrapper for our wizard
url: '/stepTwo',
templateUrl: 'stepTwo.html',
controller: 'wizardController'
})
Then later in our "wizard.html" we can have something like this :
<div id="container">
<div>
<h2>Our multistep form wizard</h2>
<div id="status-buttons" class="text-center">
<a ui-sref-active="active" ui-sref=".stepOne"><span>1</span> Step One</a>
<a ui-sref-active="active" ui-sref=".stepTwo"><span>2</span> Step Two </a>
</div>
</div>
<!-- Here we specify our view that is a container for our subviews(steps) , which in our case can be a form !-->
<form id="signup-form" ng-submit="submit()">
<!-- nested state views will be inserted here -->
<div ui-view></div>
</form>
</div>
And obviously for our steps , we must have seperated html files.
This way , we still have one controller , url will be updated , and we can also add angular animation .

Hide element outside the ng-view DOM based on route

Question:
How can I add a "Login" view/route to my angular app that hides an element that is outside the ng-view DOM?
Situation:
In my Angular page, I have a navigation tree view on the left and the main view in the center:
<div ng-app="myApp">
<div class="col-sm-3" ng-controller="TreeController">
<div treeviewdirective-here>
</div>
</div>
<div class="col-sm-9 content" ng-view="">
</div>
</div>
Each node in the treeview changes the location using something like window.location.hash = '#/' + routeForTheClickedItem;.
Using the standard routing, this works great, i.e. the tree is not reloaded each time, but only the main "window".
Problem:
I want to add a login functionality with a login view. For this view, the treeview should not be visible - only after the login. To achieve this with the normal routing, I know I could move the ng-view one level up, i.e. embed the treeview into each view - but this would result in the treeview being reloaded with every route change.
Is there an easy alternative that allows me to check what page is displayed in the ng-view? Or check some other variable set during the routing? Then I could use something like:
<div class="col-sm-3" ng-controller="TreeController" ng-show="IsUserLoggedIn">
You could listen for a routeChangeSuccess outside ng-view
$scope.$on('$routeChangeSuccess', function (event, currentRoute, previousRoute) {
//do something here
});
hope that helps, you can catch me on angularjs IRC - maurycyg
You could define a controller at the top div level.
Something like:
<div ng-app="myApp" ng-controller="MainController">
and in MainController inject a Session. Something like Session is enough to decide whether to show the tree.
Here's an example of MainController:
_app.controller('MainController', function ($scope, SessionService) {
$scope.user = SessionService.getUser();
});
Here's an example of SessionService:
_app.factory('SessionService', function() {
var user = null;
return {
getUser : function() {
return user;
},
setUser : function(newUser) {
user= newUser;
}
};
});
Of course, when you login you must set the user to the SessionService. Therefore, a SessionService has to be injected into your LoginController, too.
And finally, your html:
<div ng-app="myApp" ng-controller="MainController">
<div class="col-sm-3" ng-controller="TreeController">
<div ng-hide="user == null" treeviewdirective-here>
</div>
</div>
<div class="col-sm-9 content" ng-view="">
</div>
</div>

Resources