How to swap views in angularJS? - html

I am trying to create an angular application.
When the index.html page is loaded 2 links login and register are displayed.
When either login or register is clicked the entire view is replaced by the corresponding view.
1. Register/Login links should stay at the top and the corresponding view should be displayed below after clicking on them.
2. After successful authentication in login controller, The complete view including the login and register link should be replaced with menu-auth.html view.
I have tried using the below code, but still the 2 links disappear and login/register views appear.
Also after the http Post is fired in login controller, the menu-auth.html is displayed but appropriate css is not displayd, so I am not able to click the menu links.
I guess the menu-auth.html view is not placed in the view of index.html
index.html
<!doctype html>
<html>
<head>
<script src = "js/angular.min.js"></script>
<script src = "js/angular-ui-router.min.js"></script>
<script src = "app/app.js"></script>
<script src = "controller/login.js"></script>
<script src = "controller/register.js"></script>
<script src = "app/config.js"></script>
<style>.active { color: red; font-weight: bold; }</style>
</head>
<body>
<div ng-app="app">
<ui-view>
</ui-view>
</div>
</div>
</body>
</html>
I have two views
menu-unauth.html
<a ui-sref="login" ui-sref-active="active">Login</a>
<a ui-sref="register" ui-sref-active="active">Register</a>
<ui-view="unauth"></ui-view>
menu-auth.html
<a ui-sref=".nentry" ui-sref-active="active">Create Entry</a></br>
<a ui-sref=".ventry" ui-sref-active="active">View entry</a></br>
<a ui-sref=".logout" ui-sref-active="active">Logout</a></br>
<ui-view="auth"></ui-view>
config.js
app.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('unauth', {
url:'',
templateUrl: 'view/menu-unauth.html'
})
.state('unauth.login', {
url:'/login',
templateUrl: 'view/login.html',
controller: 'login'
})
.state('unauth.register', {
url:'/register',
templateUrl: 'view/register.html',
controller:'register'
})
.state('auth', {
url:'/menu',
templateUrl: 'view/menu-auth.html'
})
}]);
app.js
var app = angular.module("app", ['ui.router','ngCookies']);
login.js (Controller)
app.controller('login', function($scope,$http,$cookieStore,$state){
$scope.login=function(){
$scope.credentials={
UserName:$scope.email,
Password:$scope.password
};
$http({
method: 'POST',
url: 'test.com/sess',
data: $scope.credentials
}).then(function(response) {
$state.go('auth');
}
}
});

I made the following changes to (observe the ui-sref value changed to contain . dot)
menu-unauth.html
<a ui-sref=".login" ui-sref-active="active">Login</a>
<a ui-sref=".register" ui-sref-active="active">Register</a>
<ui-view></ui-view>
config.js
app.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('unauth', {
url:'',
templateUrl: 'view/menu-unauth.html'
})
.state('unauth.login', {
url:'/login',
templateUrl: 'view/login.html'
})
.state('unauth.register', {
url:'/register',
templateUrl: 'view/register.html'
})
}]);

Related

AngularJS $routeProvider: Routing is not working

For some reason, routeProvider is not working in my code when I'm clicking on the link. I can't seem to find the error.
var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/", {
template: "Order Details"
})
.when("/first", {
templateUrl: "first.html"
})
.when("/second", {
templateUrl: "second.html"
})
.when("/third", {
templateUrl: "third.html"
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
show details
show details
show details
<div ng-view></div>
Here is your fix :
Change href="#/first" to href="#!first"
And add to your angular app configuration the following lines:
.config(function ($locationProvider) {
$locationProvider.hashPrefix('!');
}
Here is the working plunkr for the same : Click Here
Since we are defining templateUrl parameter to which we provide the path of template to load, it is creating a difference. If we would have used template parameter to which we provide direct html code to load, then your code will work perfectly.

AngularJS - How to get the name of the current HTML template file for the ui-view?

My app shows an HTML page with multiple views, and each view can be conditionally built from multiple HTML templates.
I want to edit each HTML file and add a few lines at the top, something like
<div ng-if="showFileNames”>
<hr>
<p>Start of file {{how do I get the file name}}</p>
<hr>
</div>
And maybe the same at the footer.
Thus, by setting $scope. showFileNames to true, I could switch the display of file names on/off and see how my page is actually composed (is this clear, or should I add some ascii art?).
I could just hard code {{how do I get the file name}} in each file, but doing it dynamically means that I can more easily add the code to each file, plus it guards against files being renamed.
Can it be done? If so, how?
[Update] I just realized that the question didn't explain well enough. Sorry.
I need to stress that part where I said
each view can be conditionally built from multiple HTML templates
While the view is state based, its contents are built from different <ng-include> files, based on data.
So, state A might include A.html, but, based on the data, that view might <ng-include> B.html, C.html and E.html, or it might <ng-include> F.html, G.html and H.htFl - and I want to show the file name of each at the head & foot of the part of the view shown by each file
Update: You may have templates loaded with ui-view and ng-include. The example given bottom of this answer has a nice generic directive to return the corresponding template name even though if you nested ui-view and ng-include together. Click through "Home", "About" and "Named View" link inside "About".
Few theory goes below,
If you use ui-view then you can try this with $state.current.templateUrl as below.
<div ng-if="showFileNames”>
<hr>
<p>Start of file {{$state.current.templateUrl}}</p>
<hr>
</div>
The above will work if you had defined your state as below,
.state('state1', {
url: '/state1',
templateUrl: 'partials/state1.html'
controller: 'State1Ctrl'
})
But if you had defined this as named views as below,
$stateProvider
.state('report',{
views: {
'filters': {
templateUrl: 'report-filters.html',
controller: function($scope){ ... controller stuff just for filters view ... }
}
}
}
})
Then, better you can have a method assigned with the $rootScope as below and pass the $state.current.views from the html to the function.
$rootScope.getTemplate = function(view) {
var keys = Object.keys(view);
if(keys.length === 0) return '';
return view[keys[0]].templateUrl;
};
and the html,
<div ng-if="showFileNames”>
<hr>
<p>Start of file {{getTemplate($state.current.views)}}</p>
<hr>
</div>
But you can have a look at the below generic directive which covers ui-view, nested ui-view, named ui-view and ng-include and even a bit of complex nesting with ui-view and ng-include.
Generic directive with an example page
Click through "Home", "About" and "Named View" link inside "About"
var app = angular.module('app', ['ui.router']);
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home.html',
controller: 'TestController'
})
.state('about', {
url: '/about',
templateUrl: 'about.html',
controller: 'TestController'
})
.state('about.named', {
url: '/named',
views: {
'named': {
templateUrl: 'named.html',
controller: 'TestController'
}
}
});
}
]);
app.controller('TestController', function($scope) {
});
app.directive('templateName', ['$state', function($state) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var templateName = $state.current.templateUrl;
var includesParent = $(element).closest('[ng-include]');
if(includesParent && includesParent.length > 0) {
if(includesParent.find('[ui-view]').length === 0) {
templateName = scope.$eval(includesParent.attr('ng-include'));
}
}
if(!templateName && $state.current.views) {
var uiViewParent = $(element).closest('[ui-view]');
var viewName = $state.current.views[uiViewParent.attr('ui-view')];
if(viewName) {
templateName = viewName.templateUrl;
}
}
element.html(templateName);
}
};
}]);
angular.bootstrap(document, ['app']);
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.min.js"></script>
<div>
<!-- NAVIGATION -->
<nav class="navbar navbar-inverse" role="navigation" ng-include="'nav.html'">
</nav>
<!-- MAIN CONTENT -->
<div class="container">
<!-- THIS IS WHERE WE WILL INJECT OUR CONTENT ============================== -->
<div ui-view></div>
</div>
<script type="text/ng-template" id="home.html">
<h3>Home Page</h3>
<p>Start of file: <span template-name></span></p>
</script>
<script type="text/ng-template" id="about.html">
<h3>About Page<h3>
<p>Start of file: <span template-name></span></p>
<div ng-include="'aboutUs.html'"></div>
</script>
<script type="text/ng-template" id="aboutUs.html">
<h3>About us<h3>
<p>Start of file: <span template-name></span></p>
<a ui-sref="about.named">Named View</a>
<div ui-view="named"></div>
</script>
<script type="text/ng-template" id="named.html">
<h3>Named View<h3>
<p>Start of file: <span template-name></span></p>
</script>
<script type="text/ng-template" id="nav.html">
<div class="navbar-header">
<a class="navbar-brand" ui-sref="#">Start of file: <span template-name></span></a>
</div>
<ul class="nav navbar-nav">
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="about">About</a></li>
</ul>
</script>
</div>

angular ui-router ui-view inside ui-view issue

index.html
<div ui-view></div>
test.html is loaded on index.html's ui-view
and inside of test.html
<div ui-view="content"></div>
and tried to load another html files but it's not working
here is my ui-router
.state("index", {
url: "",
templateUrl: "views/index.html",
controller : 'MainCtrl',
controllerAs : 'main'
})
.state("test", {
url: "/test",
templateUrl: "views/test.html",
controller : 'testCtrl',
controllerAs : 'test'
})
.state("test.another", {
url : "another/",
views:{
'content':{
templateUrl :'views/another.html'
}
}
})
so basically what I expect is
<div ui-view>
<!-- test.html -->
<div ui-view="test">
<!-- another.html -->
</div>
</div>
I see two problems:
.state("test.another", {
templateUrl: "views/test.html",
views:{
'another#post':{
templateUrl :'views/another.html'
}
}
})
That first templateUrl isn't required; it's only for views, not states.
Also:
'another#post':{
This means you're targeting a view 'another' in 'post.html'. You neither have a view named 'another', nor a template 'post.html'.

Unable to fetch data from controller in multiple html page in angularjs

I am trying to make a webpage.In that when a user login , a new html page("dashboard.html")opens in the view. This "dashboard.html" contains some links(links to other html pages).When user clicks on them a new html(say "page_3.html") page should open with data that is present in controller.this "page_3.html" is not fetching data from controller.Below is my code.
<!-- controller.js -->
var app = angular.module('myApp',[ 'ngRoute' ]);
app.config(function($routeProvider){
$routeProvider
.when('/',{
templateUrl: 'login.html'
})
.when('/dashboard',{
templateUrl: 'dashboard.html'
})
.when('/page_3',{
templateUrl: 'page_3.html'
})
.otherwise({
redirectTo : '/'
});
});
app.controller('app', function($scope, $location){
$scope.item = "test";
$scope.submit = function(){
$location.path('/dashboard');
}
};
});
<!DOCTYPE html>
<html>
<head>
<title>Project</title>
<script src="angular.js"></script>
<script src="angular-route.js"></script>
<script src="controller.js"></script>
</head>
<body ng-app= "myApp" ng-controller="app">
<div ng-view></div>
</body>
</html>
<!-- below is login.html page -->
<div ng-controller="app">
<form action="/">
<button type="button" ng-click="submit()">Login</button>
</form>
</div>
<!-- below is my dashboard.html page -->
<div ng-controller="app">
<h1>Page_3</h1>
<div><a href='page_3.html'>page_3</a></div>
</div>
<!-- below is page_3.html page -->
<div ng-controller="app">
<p>{{item}}</p>
</div>
result : {{item}}
May I suggest avoiding the ng-controller directive and rather use the controller config object on your router?
.when('/page_3',{
templateUrl: 'page_3.html',
controller: "app"
})
There are two main problems with your code:
Enable HTML 5 mode for pushState via $locationProvider for URLs like /dashboard and /page_3
Fix the problem where route is configured for /page_3 but having a a tag pointed to /page_3.html
To get a working example:
Add a base tag
<base href="/">
Enable html5 mode via locationProvider in a config block
$locationProvider.html5Mode(true);
Fix route in dashboard.html
<!-- below is dashboard.html page -->
<div ng-controller="app">
<h1>Page_3</h1>
<div><a href='page_3.html'>page_3</a></div>
</div>
Click here for the demo / jsbin.
Other/suggestions: as Zack Briggs have suggested; using controller syntax in routes would help you come up with better code structure / design in router config, directives, or components. Also putting everything in one place is often a bad idea for a growing project.

Angular loads HTML index instead of ng-app.js on refresh

I am playing around with adding in an Angular-UI router which is working perfectly when I click on links within my application. For example, if I go from / to /feed/9 it will load in the /partials/post.html file into the ui-view div and I can then use the '9' held in $stateParams to populate the template with the data from post 9. However if I refresh the page, the site breaks and Angular tries to load index.html as the ng-app.js file? I have no idea what is happening here. I've uploaded some screenshots to demonstrate this and I've included my node server, angular routing and the relevant html partials. I have no idea where this is going wrong so I can provide any additional data and any help would be greatly appreciated!
Working fine when coming from another link on '/'
On refresh!!
Node - server.js
var = /* Dependencies and vars */;
mongoose.connect(dbConfig.url, dbConfig.options);
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));
app.use(bodyParser());
app.use(flash());
require('./routes/api.js')(app); //For CRUD operations on the database
require('./routes/api_proc.js')(app); //Protected endpoints for CDN
require('./routes/api_ext.js')(app); //For getting data from GCal, fb, Twitter and Instagram
/* The following code is a url rewrite to pass all
further get requests that aren't defined in the
above routing files through the index page and
hence through the Angular 'frontend' routes */
app.use(function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
app.listen(port);
Angular ng-app.js
var app = angular.module('app', ['ui.bootstrap', 'ngResource', 'ui.router']);
//Using state ui-router
// ROUTES
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url : '/',
templateUrl : 'partials/home.html'
})
/* ... */
.state('feed', {
url : '/feed',
templateUrl : 'partials/feed.html'
})
.state('post', {
url : '/feed/{id:.*}',
templateUrl : 'partials/post.html',
controller: 'postController'
})
$locationProvider.html5Mode(true);
});
app.factory("Feed", function($resource) {
return $resource("/api/feed/:id", {}, {
query: {
isArray: true
}
});
});
app.controller("postController", function($scope, Feed, $stateParams) {
var feed = Feed.query();
feed.$promise.then(function(promiseData) {
postArray = promiseData.slice(0,promiseData.length);
$scope.feed = promiseData;
$scope.id = $stateParams.id;
});
});
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<!-- CDN -->
<!-- Angular, Bootstrap, Angular modules, etc. -->
<!-- Styles -->
<!-- Angular Script import -->
<script type="text/javascript" src="ng-app.js"></script>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<nav><!--Bootstrap nav--></nav>
<div ui-view></div>
<footer></footer>
<script>
//For Bootstrap tooltips which are in some of the partials.
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
$('[rel=tooltip]').tooltip();
});
</script>
</body>
</html>
/partials/post.html
<div class="container-fluid main-content">
<header class="banner" class="row">
<h1 class="page-title">{{id}}</h1>
</header>
<!-- Main page info -->
</div>
I think you have relative paths pointing to your css files.
When you load page from /feed/9 then links are invalid.
Maybe it happens also for templates referenced from angular.