Single Page Application View Location - javascript

I think I have a gross misunderstanding as to how routing in AngularJS works, and SPA's altogether.
I had thought with my simple routing :
$routeProvider
.when('/home', {
templateUrl: 'app/views/home.html',
controller: 'homeController'
})
.when('/login', {
templateUrl: 'app/views/login.html',
controller: 'loginController',
})
I had thought that when I went to /login, angular made an ajax call to grab the html page it needed. However, I don't see any calls going through fiddler, and that doesn't really make sense.
But I can't seem to locate where the pages are in my Chrome Developer Tools, nor find the correct word combination to get a suitable answer through google. Can someone clear this up for me?
if it helps, here's the body of my layout page:
<body ng-cloak>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
...nav stuff
</nav>
<br/><br/>
<div class="container body-content" ng-view></div>
<!-- 3rd party scripts -->
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-local-storage.min.js"></script>
<script src="Scripts/jquery-2.1.1.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>
<!-- app main -->
<script src="app/app.js"></script>
<!-- controllers -->
<script src="app/controllers/homeControllers.js"></script>
<script src="app/controllers/loginController.js"></script>
<!-- services -->
<script src="app/services/modelErrorService.js"></script>
<script src="app/services/authInterceptorService.js"></script>
<script src="app/services/authService.js"></script>
</body>
EDIT
Sorry I may have been unclear. The code works fine. My question is, when angular routes you to a new page, where is it loading that html template from? Is it all delivered to the client at the get-go, or is it calling back to the server? If it is on the client, where is it stored?

If templateUrl is specified, Angular will look into the $templateCache for the template and load it from there if found. If not found, it will try to fetch it from the server, store it in $templateCache for future access and load it into view.
Templates can be put into Angular's $templateCache
when fetched from the server for the first time
by placing them in the HTML, in a <script type="text/ng-template"></script> element
by programmatically putting them into the $templateCahce (for whatever reason: performance, offline access etc)

Your code looks just fine.
Have you injected the ngRoute module into your application like so:
angular.module('your-app-name', ['ngRoute']);

Related

Angular Material and md-nav-bar routing

I'm digging into Angular and have decided to use the Angular Material library to assist in my first application. So far I have some very basic code I copied from https://material.angularjs.org/1.1.0/demo/navBar which I have modified to fit my own needs. I'm having some trouble wrapping my head around routing and the md-nav-items.
<html>
<head>
<title>PRT - CIT</title>
<meta name="viewport" content="width=device-width, initial-scale=1" </meta>
<!-- Angular Material style sheet -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"> </head>
<body ng-app="MyApp" id="bootstrap-overrides">
<div ng-controller="AppCtrl" ng-cloak="" class="navBardemoBasicUsage main">
<md-content class="md-padding">
<md-nav-bar md-selected-nav-item="currentNavItem" nav-bar-aria-label="navigation links">
<md-nav-item md-nav-click="goto('queue')" name="queue">Queue</md-nav-item>
<md-nav-item md-nav-click="goto('detail')" name="detail">Detail</md-nav-item>
<md-nav-item md-nav-click="goto('request')" name="request">Request</md-nav-item>
<!-- these require actual routing with ui-router or ng-route, so they won't work in the demo
<md-nav-item md-nav-sref="app.page4" name="page4">Page Four</md-nav-item>
<md-nav-item md-nav-href="#page5" name="page5">Page Five</md-nav-item>
--></md-nav-bar>
<div class="ext-content"> External content for `<span>{{currentNavItem}}</span>` </div>
</md-content>
</div>
<script src="node_modules/angular/angular.js"></script>
<script src="node_modules/angular-resource/angular-resource.js"></script>
<script src="node_modules/angular-animate/angular-animate.js"></script>
<script src="node_modules/angular-route/angular-route.js"></script>
<script src="node_modules/angular-aria/angular-aria.js"></script>
<script src="node_modules/angular-messages/angular-messages.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="node_modules/angular-material/angular-material.js"></script>
<script src="js/site.js"></script>
<link rel="stylesheet" href="/css/site.css">
</body>
</html>
Here's my JS:
(function () {
'use strict';
var MyApp = angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ngRoute']).controller('AppCtrl', AppCtrl);
function AppCtrl($scope) {
$scope.currentNavItem = 'queue';
}
MyApp.config(function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/index.html'
, controller: 'AppCtrl'
}).when('/queue', {
templateUrl: '/partials/queue.html'
, controller: 'AppCtrl'
}).when('/detail', {
templateUrl: '/partials/detail.html'
, controller: 'AppCtrl'
}).when('/request', {
templateUrl: '/partials/request.html'
, controller: 'AppCtrl'
});
});
})();
I'm kind of lost as to how I should route the tabs. From what I've read, md-nav-bar has some routing built in, but I've found examples utilizing ngRoute as well ui-router.
I'm also confused as to actually populate my partial views in the
<div class="ext-content"> External content for `<span>{{currentNavItem}}</span>` </div>
I tried using md-nav-href instead of md-nav-click but it just ended up redirecting me to the pages, not populating the content below my tabs/nav-bar; I rolled back the JS I had written and that part of the HTML. I've read the other questions posted in this area that I could find but none addressed rendering different partials based on nav-bar item. Any suggestions? I was thinking I could monitor currentNavItem and have the right partial render based on the value of it, but again, I'm not sure how to actually do the rendering.
Here is a Plnker that doesn't render correctly in the preview for some reason, but the code is the same as what I have locally.
Here is an image of what it looks like running locally.
Thanks in advance!
Final Edit:
S/O to #Searching for helping me get it working below. I've updated the plnker link to reflect the changes. Note it gets a little laggy due to the base append script.
ngRoute: When $route service you will need ng-view container. This will be used to load all you routed pages.
You do not have a goto() so just use simple md-nav-href tags to navigate around. The currentNavItem is set by md-selected-nav-item which is not what you need. Let's route with your setup
index.html : update your links to look like this. Use md-nav-href
<md-nav-item md-nav-href="queue" name="queue">Queue</md-nav-item>
index.html : when using html5Mode you will need base tag. Instead of manually specifying it just use the script below. Make sure you load angular.js before this script.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<script type="text/javascript">
angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
</script>
script : enable html5molde, why.. too many resources out there. I encourage you to lookup :)
MyApp.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true)
$routeProvider.when('/', {
templateUrl : 'index.html',
controller : 'AppCtrl'
}).when('/queue', {
templateUrl : 'queue_partial.html',//actual location will vary according to your local folder structure
controller : 'AppCtrl'
}).when('/detail', {
templateUrl : 'detail_partial.html',
controller : 'AppCtrl'
}).when('/request', {
templateUrl : 'request_partial.html',
controller : 'AppCtrl'
});
});

How does one map many routes in AngularJS?

An AngularJS site with a Spring Boot backend has numerous public url patterns in addition to a secure section. All the public url patterns fall in the model mydomain.com/public1, mydomain.com/public2, mydomain.com/public3, and so on, while all the secure content will be inside the mydomain.com/secure url pattern like mydomain.com/secure/one_of_many_urls. The problem is that the sample app I am starting with has separate modules for every route. This would become hard to maintain with n routes.
How can I set the code up so that all the public1, public2, public3, public_n routes share a single controller?
Here is the current directory structure. I would like for the public1 directory to turn into public and be able to map as many specific url patterns as I want to put into it:
In addition, my public1.js is currently empty as follows:
angular.module('public1', []).controller('public1', function($scope, $http) {
});
The link to the public1 route is handled in a navigation bar in index.html as follows:
<!doctype html>
<html>
<head>
<title>Hello Angular</title>
<!-- To produce natural routes (without the #), you need an extra <base/> element in the header of the HTML in index.html, and you need to change the links in the menu bar to remove the fragments ("#"). There are also changes in a spring controller and in the main js module. -->
<base href="/" />
<link href="css/angular-bootstrap.css" rel="stylesheet">
<style type="text/css">
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
</style>
</head>
<body ng-app="hello" ng-cloak class="ng-cloak">
<div ng-controller="navigation" class="container">
<ul class="nav nav-pills" role="tablist">
<li ng-class="{active:tab('home')}">home</li>
<li ng-class="{active:tab('message')}">message</li>
<li ng-class="{active:tab('public1')}">public1</li>
<li>login</li>
<li ng-show="authenticated()">logout</li>
</ul>
</div>
<div ng-view class="container"></div>
<script src="js/angular-bootstrap.js" type="text/javascript"></script>
<script src="js/auth/auth.js" type="text/javascript"></script>
<script src="js/home/home.js" type="text/javascript"></script>
<script src="js/message/message.js" type="text/javascript"></script>
<script src="js/public1/public1.js" type="text/javascript"></script>
<script src="js/navigation/navigation.js" type="text/javascript"></script>
<script src="js/hello.js" type="text/javascript"></script>
</body>
</html>
And public1.html is:
<h1>Public 1</h1>
<div>
<p>This will be a public url pattern.</p>
</div>
How do I change the code below so that a scaling n number of public routes can efficiently share the same controller? Each public_n route will have their own images, but would share js logic, if they have any js logic.
I found the following, but where would one put it in the code above, and how would a person link everything to it without resorting to leaving it in hello.js?
.when('/public1', {
templateUrl: 'js/public/public1.html'
}
.when('/public2', {
templateUrl: 'js/public/public2.html'
}
.when('/public3', {
templateUrl: 'js/public/public3.html'
})
How do I change the code below so that a scaling n number of public
routes can efficiently share the same controller?
You can Associate one Controller to Many Routes (Views) just assigning it to more routes in your $routeProvider as follows:
myApp.config(function ($routeProvider) {
$routeProvider
.when('/public1', {
templateUrl: 'js/public/public1.html',
controller: 'myController'
})
.when('/public2', {
templateUrl: 'js/public/public2.html',
controller: 'myController'
})
.when('/public3', {
templateUrl: 'js/public/public3.html',
controller: 'myController'
})
.otherwise({
redirectTo: '/'
});
})
You can also Set a Controller Alias as follows:
.when('/public1', {
templateUrl: 'js/public/public1.html',
controller: 'myController',
controllerAs: 'myCtrl'
})
I found the following, but where would one put it in the code above,
and how would a person link everything to it without resorting to
leaving it in hello.js?
If I got your question, you just need to put the $routeProvider in a separated routeProvider.js file and include it in your index.html. Same thing for your controller/controllers.
I suggest you to take a look at:
AngularJS Controllers Documentation
AngularJS $routeProvider Documentation
Follow the first lesson of - CodeSchool - Staying Sharp with AngularJS
EggHead.io AngularJS Screencasts
And also take a look at those Q/A on StackOverflow:
Using one controller for many coherent views across multiple HTTP requests
Views sharing same controller, model data resets when changing view
Controlling multiple views in one controller in AngularJS
Can I use one controller updating two views in AngularJS?
I hope I've been helpful.

Structuring templates in an AngularJS SPA - are there performance issues when using ng-include a lot?

I was wondering what the best way to structure templates in an AngularJS SPA. So far I have kind of a rails approach, but I'm not sure if this is a good idea.
What I mean is that I for example have a /js/app/views/partials folder where I have snippets of html that are used in different places. This could be a form or a preview of content, basically everything that is used all over the app. I like this structure because let's say you have a comment form that appears in 5 different places and you want to add a field: Changing one file rather than 5 is much better.
I then for example have a /js/app/views/home.html template, that is referenced by my ui-router and loaded in ui-view in /index.html which only serves as layout.
/js/app/routes.js
myModule.config([
'$stateProvider',
'$urlRouterProvider',
'$locationProvider',
function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: '/js/app/views/home.html',
controller: 'MainCtrl',
resolve: {
// resolve code
}
});
}
]);
/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base href="/">
<title><%= title %></title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link rel='stylesheet' href='/css/style.css' />
<script src="/js/angularjs-1.3.16.min.js"></script>
<script src="/js/angular-ui-router-0.2.15.js"></script>
<script src="/js/app/app.js"></script>
<script src="/js/app/routes/routes.js"></script>
<script src="/js/app/services/services.js"></script>
<script src="/js/app/controllers/controllers.js"></script>
</head>
<body ng-app="myApp" ng-controller="MainCtrl">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
</body>
</html>
/js/app/views/home.html
<div class="page-header">
<h1>v2</h1>
</div>
<div ng-include src="'/js/app/views/partials/post-form.html'"></div>
<div ng-repeat="post in posts">
<div ng-include src="'/js/app/views/partials/post-preview.html'"></div>
</div>
So the ui-router is called with the home state and injects the /js/app/views/home.html in /index.html (at ui-view). home.html itself includes two partials /js/app/views/partials/post-form.html and /js/app/views/partials/post-preview.html.
The result are a lot of XHR requests for a single page load. That cannot be good for performance.
Is there a better way to do that? Or can I just not structure my views with so many partials and have to use fewer files and repetitive code?
My backend / server is NodeJS with Express. So maybe it would also be an option to do that server-side, using express partials.

angular js ng-view returns blanc partials -- Express/ Jade

I am writing an angular application following a tutorial. To my surprise, i followed exactly and my node js is starting fine without an issue. However, my angular is not returning the template as suppose to . I saw a similar problem here same tutorial and the same issue. However, the question was not answered . Below is my dir structure
app.js
var app = angular.module('app', ['ngResource', 'ngRoute']);
angular.module('app').config(function($routeProvider, $locationProvider){
$locationProvider.html5Mode(true);
$routeProvider
.when('/', { templateUrl: 'partials/main', controller: 'mainCtrl'});
});
angular.module('app').controller('mainCtrl', function($scope){
$scope.myVar = "Hello Angular";
});
My layout.jade
doctype html
head
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
My main.jade
h1 This is a partial
h2 {{ myVar }}
The route in my server.js are set as
app.get('partials/:partialPath',function(req,res){
res.render('partials/' + req.params.partialPath);
});
app.get('*', function(req,res){
res.render('index');
});
my index.jade
extends ../includes/layout
block main-content
section.content
div(ng-view)
Althought i am thinking that shouldn't be an issue because i am starting with a partial view which is part of a page. When i run, my page return black. I inspect the element and ensured that all the js and css where loaded. When i view the source, a html source below was generated.
<!DOCTYPE html>
<head><link rel="styleSheet" href="css/bootstrap.css">
<link rel="styleSheet" href="vendor/toastr/toastr.css">
<link rel="styleSheet" href="css/site.css">
</head>
<body ng-app="app">
<section class="content">
<div ng-view></div></section>
<script type="text/javascript" src="vendor/jquery/dist/jquery.js"></script><script type="text/javascript" src="vendor/angular/angular.js"></script>
<script type="text/javascript" src="vendor/angular-resource/angular-resource.js"></script>
<script type="text/javascript" src="vendor/angular-route/angular-route.js"></script><script type="text/javascript" src="app/app.js"></script>
</body>
I was suspecting routeProvider from my app.js here
.when('/', { templateUrl: 'partials/main', controller: 'mainCtrl'});
tried
.when('/', { templateUrl: '/partials/main', controller: 'mainCtrl'});
All to no avail . please where do i go wrong ? I have tried everything possible. I even restarted the tut yet still blanc. any help would be appreciated.
Thank you for your time. It turns out the issue is in my layout
doctype html
head
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
Changed to
doctype html
head
base(href='/')
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
What was missing is
base(href='/')
It does not load the templates if you remove that base. I learnt that from another tut video by tut plus "[Tuts Plus] Building a Web App From Scratch With AngularJS Video Tutorial" . The presenter specifically mentioned the important of the base(href='/') and warned never to forget . Alternatively , there is another good example from #Alex Choroshin answer here . you should download the doc he suggested . Its a perfect example. Thanks

ng-view Angular not showing the text output

<html>
<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="angular-route.js"></script>
</head>
</head>
<body ng-app="myApp" ng-controller="cont1">
<a href=#dogs>dogs</a> <a href=#cats>cats</a>
<div ng-view></div>
<script>
angular.module("myApp", ['ngRoute']).config ('$routeProvider',function($routeProvider){
$routeProvider.when("/dogs", {templateUrl: "one.html"})
.when("/cats", {templateUrl: "two.html"})
.otherwise("/cats", {redirectTo: "/dogs"})
});
app.controller("cont1", function($scope){ $scope.model = {message: "This is my app One!!!"} });
</script>
</body>
</html>
I am unable to get the message in paragraph 'Here are the cats' or 'Here are the dogs' on clicking the two links; these files are saved as one.html and two.html in the same folder.
I have downloaded and added the angular-route.js file in the same folder. Kindly help!
I have put controllers in routerProvider but it is not necessary, and adding it to it wont run! :(
You are forgetting to insert the controllers for your templates inside the object in when. See below:
<html>
<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="angular-route.js"></script>
</head>
</head>
<body ng-app="myApp" ng-controller="cont1">
<a href=#dogs>dogs</a> <a href=#cats>cats</a>
<div ng-view></div>
<script>
angular.module("myApp", ['ngRoute']).config ('$routeProvider',function($routeProvider){
$routeProvider.when("/dogs", {
templateUrl: "one.html",
controller: "cont1"
})
.when("/cats", {
templateUrl: "two.html",
controller: "cont1"
})
.otherwise("/cats", {redirectTo: "/dogs"})
});
app.controller("cont1", function($scope){ $scope.model = {message: "This is my app One!!!"} });
</script>
</body>
</html>
If you're opening this html file directly in the browser, it won't work. This is because your template files will be loaded using AJAX. To make sure the user's data from one site cannot be fetched by a malicious other site, AJAX requests must adhere to the Same origin policy. The minute details of this policy are outside the scope of this answer, but it means that one site page can't make requests to another site. Files loaded directly from disk (loaded using the `file://' url scheme) don't have an origin so the cross origin policy check will always fail.
To solve this problem, put your files on a server, and try acessing them from there. If you're using a mac, you canuse Python's simple http server, which comes preinstalled on your mac. On windows, you can use mongoose.
When you use the minify-proof syntax for angular you pass the parameters as an array, so instead of:
config('$routeProvider',function($routeProvider){
$routeProvider.when("/dogs", {
...
});
you needed:
config(['$routeProvider',function($routeProvider){
$routeProvider.when("/dogs", {
...
}]);
http://plnkr.co/edit/7NiWduPXCIKutSF243Hg?p=preview
I checked it out with Team. I just had to remove the controller from the top part of the code in Html file, and it would work fine.
<body ng-app="myApp" ng-controller="cont1">
should be turned to ...
<body ng-app="myApp">
Thanks buddies for helping me though!

Categories

Resources