How to create a layout template for angular routing? - javascript

I use angular routing:
angular.module("app-test", ["ngRoute"]).config(function ($routeProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$routeProvider.when("/",
{
controller: "firstController",
templateUrl: "/views/first/index.html"
});
$routeProvider.when("/second",
{
controller: "secondController",
templateUrl: "/views/second/index.html"
});
$routeProvider.otherwise({ redirectTo: "/" });
});
But all my views of the different routes (e.g. views/first/index.html, views/second/index.html, etc.) have repeating html code like loading panels, messages, etc.
How can I outsource those common syntax in for example a layout html page that is used together with all the templateUrl views of the angular routing?
For example if every templateUrl has following html code - <div>{{message}}</div> - I would like to put this code in an extra html file which will be included in the templateUrl while the angular routing is getting the view.

You can use ng-include. But you can also use the same View (html) with different controllers:
$routeProvider.when("/",
{
controller: "firstController",
templateUrl: "/views/shared.html"
});
$routeProvider.when("/second",
{
controller: "secondController",
templateUrl: "/views/shared.html"
});
Please also note that a "views" folder doesn't scale very well. It works better to have a feature directory for each feature that contains all the pieces needed to build that feature. Shared stuff can get a bit dicey--if you know in advance you're going to share it, you can put it in a "shared" or "common" directory, but sometimes you wind up using it from the feature where it was first used.

Related

Angular Route for specific url

I'm currently working on a MEAN stack project and am trying to get a specific template to display on a specific url.
Currently if users goto www.myurl/catalog, it loads the catalog.html template, as it would with any /catalog?catagory=productType url.
I would like it so that when users go to /catalog?category=specificProductType that it loads the catalogSpecific.html template. Currently, the catalog.html template supersedes the catalogSpecific.html template. I can't find much about this specific issue so any help would be appreciated.
Currently my routes look like this:
app/front/app.js
angular.module('app', ['ngRoute',
'app.LandingModule.controller',
'app.CatalogModule.controller',
'app.ProductModule.controller',
'app.HeaderModule.directives',
'app.FooterModule.directives'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'html/landing.html',
controller: 'LandingController'
})
.when('/catalog', {
templateUrl: 'html/catalog.html',
controller: 'CatalogController'
})
.when('/catalog?category=specificProductType', {
templateUrl: 'html/catalogSpecific.html',
controller: 'CatalogController'
})
.otherwise({
redirectTo: '/'
});
}]);
EDIT: Seems I was wrong about this not being possible with the default router. As Hadi describes in their comment, you can replace "templateUrl" with a function that returns a template url given the current route.
To my knowledge you cannot route the way that you want to with the built-in angular router.
As far as I can see you have two options to go with from here:
1: Learn to use the ui-router library (found here: https://github.com/angular-ui/ui-router)
2: Send all routes from /catolog to a controller/page that manually looks at your route-params and re-routes you based off of that manually. (see https://docs.angularjs.org/api/ngRoute/service/$routeParams)
Try use templateUrl function like to this. I have not tested.
templateUrl: function($location){
if($location.category)
return 'html/catalogSpecific.html';
else
return 'html/catalog.html';
},
Demo
I was able to figure this out following Hadi's example:
.when('/catalog', {
templateUrl: function($location){
if($location.category == "specificProductType") {
return 'html/catalogSpecific.html';
} else {
return 'html/catalog.html';
}
},
controller: 'CatalogController'
})

Angularjs routes are coming upto localhost only

I have to setup a wordpress site which was developed by another team locally. They used angularjs. I am very new to angular. I placed the wordpress files in wamp server. The name of the folder is playbook.
When I tried to access the site by using url localhost/playbook, I got a javascript error saying localhost/home not found.
I checked the javascript file and I saw routing like this
.when('/', {
controller: 'HomeCtrl',
templateUrl: '/home'
})
When I added /playbook at the start like below of templateUrl, page displayed
.when('/', {
controller: 'HomeCtrl',
templateUrl: '/playbook/home'
})
Why is this happening. Shouldn't the route take the path up to localhost/playbook?
You need to specify the extension .html for the template.Assuming your file is called home.html, replace your current code with
.when('/', {
controller: 'HomeCtrl',
templateUrl: '/playbook/home.html'
})
Regarding the usage of a more specific path.Consider this, you are coding a multi-module app in Angular.To seperate concerns, you may have a file structure that is based on each module.So my routes could look something like this. For my file, this was defined in app.js , which was inside the JS folder in my whole application.Additionally, you may choose to define routes in a seperate folder altogether. There is no reason for it to default to a particular file or folder.
foodApp.config(['$routeProvider',function($routeProvider){
$routeProvider.when('/',
{
templateUrl:'js/apps/choiceScreen/choice.html',
controller:'choiceCtrl'
})
.when('/cafe',
{
templateUrl:'js/apps/cafe/cafeScreen.html',
controller:'cafeCtrl'
})
.when('/showCafe/',
{
templateUrl:'js/apps/eachScreen/itemView.html',
controller:'itemCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);

Modularity vs Performace with respect to ng-include in an angular app

Recently, I have been refactoring someone else's code. The requirement ( I'm not decision maker) is to break down large junk of html (around 1500 lines). I am porting the existing code to angular app.
I have little confusion with modularity v/s performance.
Exact problem with code:
There is main.html file which is 1500 lines. I have broke that file into
main_bar.html, main_content.html, main_map.html and main_locations.html.
Now main.html contains,
<div ng-include src="'views/main_bar.html'"/>
<div ng-include src="'views/main_content.html'"/>
<div ng-include src="'views/main_map.html'"/>
<div ng-include src="'views/main_locations.html'"/>
In app.js,
angular.module('ngBApp', ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
});
In MainCtrl,
'use strict';
angular.module('ngBApp')
.controller('MainCtrl', function ($scope) {
// some logic to fetch data and show
// in different html chunks included via ng-include
});
Although, this approach follows the modularity principle, doesn't it add overhead of downloading small junks of html with different http requests (with more header i.e, 4x header and other data) ?
Is there any other way to design app in angular way preserving performance and yet a modular code ?
Is there any other way to design app in angular way preserving
performance and yet a modular code ?
Well, why not to use Gulp or Grunt to concatenate the resulting HTML file from pieces? Or you can even build resulting HTML from template using includes.
I am strongly against using ng-include's to break long html apart.

Using Angular with no template page

I have some routes with some views that use my index.html as template. On a specific view (for instance login page) I don't want to use index.html as template. How to do this with Angular:
My routes:
.when('/user/:id/update',{
templateUrl: 'views/updateUser.html',
controller: 'updateUserCtrl'
})
.when('/role', {
templateUrl: 'views/role.html',
controller: 'RoleCtrl'
})
.when('/login', {
controller: 'RoleCtrl' //Here I want a page withou template
})
I already tried use ui-route like this:
$stateProvider
.state('contacts', {
abstract: true,
template: '<ui-view/>',
url: '/contacts'
})
.state('contacts.list', {
// loaded into ui-view of parent's template
templateUrl: 'contacts.list.html',
url: '/list'
})
.state('contacts.detail', {
// loaded into ui-view of parent's template
templateUrl: 'contacts.detail.html',
url: '/detail'
})
In Both cases my pages always inherit from my index.html.
with ui-router at least you can do abstract: true to set the route to no template and stack controllers onto views for separated behavior.
https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views
otherwise, with vanilla angularjs, theoretically you could just do template : "" if you wanted to load a controller with no template.
http://weblog.west-wind.com/posts/2013/Oct/15/Routing-to-a-Controller-with-no-View-in-Angular
The way it works is not recommended, because your browser reloaded all content of your app and it breaks all concept of a Single Page Application.
One of approaches is using ng-view/ui-view in your template (html file) and $location in your service/controller to replace the url address if user authentication was ok.
Take a look in this plnkr with two examples that work:
http://plnkr.co/edit/vPyH5lwbwYCMx6RCnVb0?p=preview
For the views where you do not want index.html's base template (header, footer, etc) to appear - you can use a div that overlays the entire page (in that component's html and css).

How to split AngularJS application into smaller modules and handle routing correctly?

What would be the best way to split AngularJS application into smaller pieces/module? For example if I have a blog post and commenting enabled for that, I think I could break it down to modules like "posts" and "comments"(?) (maybe not the best example, but the idea is to split the application logic into separate modules rather than building a huge one-module-app).
I've tried to bootstrap both modules in the separate DOM nodes and use routing in both of the modules accordingly. There are few problems:
As a "single-page" application I'm bootstrapping comments module to be used even on the front page even though it's not used there.
Since I'm not able to use multiple ng-views inside ng-app, I'm forced to write all the wrappers for my modules in the index.html view and bootstrap them? Should it be like that? Seems a bit wrong. How/where should I bootstrap those?
Are there any tips for the routing? Should I spread those in the modules or should I combine them all together somehow? (creating one "blog" module to include "posts" and "comments" modules as dependencies would still make it hard to define for example the "/post/:id" routing..?)
index.html
<div class="post"><ng-view></ng-view></div>
<div class="comments"><ng-view></ng-view></div>
javascript.js
angular.module('posts', []).config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
'template': 'Showing all the posts',
'controller': 'postCtrl
})
.when('/post/:id', {
'template': 'Showing post :id',
'controller': 'postCtrl
});
}]);
angular.module('comments', []).config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/post/:id', {
'template': 'Showing post :id comments',
'controller': 'CommentsCtrl'
});
}]);
angular.bootstrap($('.post'), ['posts']);
angular.bootstrap($('.comments'), ['comments']);
I would divide the app in "view modules" and these sub modules.
Then I use the $routeProvider to switch between the views. I define the different routing config in each module.
If I need further submodules, I load these with ng-include.
/* App Module */
angular.module('MyApp', ['MyApp.home', 'MyApp.blog'])
.config( function myAppConfig ( $routeProvider ) {
'use strict';
$routeProvider.otherwise({ redirectTo: '/home' });
});
/* home Module */
angular.module('MyApp.home', [])
.config(['$routeProvider', function config( $routeProvider ) {
$routeProvider.when('/home', {
controller: 'HomeController',
template: '<p>This is my Home</p>'
});
}]);
I created a little repository on github to explain this.
You can define routes in the submodules:
angular.module('app', ['ngRoute', 'app.moduleX'])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
//Handle all exceptions
$routeProvider.otherwise({
redirectTo: '/home'
});
})
angular.module('app.moduleX', []).config(function($routeProvider) {
$routeProvider.when('/settings', {
templateUrl: 'partials/settings.html',
controller: 'SettingsCtrl'
});
})
I also wrote a blog post about this topic.
We're doing something similar with a portal app and sub-apps. A few things we've discovered:
Only one "app" can have routes and routeParams. Because of this, if the "sub-app" needs access to the $routeParams, you either have to go "old school" for URL parsing, or use an event service.
Speaking of events, there is no Angular service for the apps to communicate, so you'll need to roll your own event service talking to root scope for both apps and inject it into both apps.
I can't see where we used ng-view for the "sub-app". Apparently bootstrapping directly to an element works similarly.
Because only one app can have routes, the apps should be bootstrapped in order. So something like this:
$( function () {
$.when(angular.bootstrap($('.post'), ['posts'])).done( function() {
console.log('POSTS: bootstrapped');
//Manually add the controller to the comments element. (May or may not be
//necessary, but we were doing something that required it to work.)
$('.comments').attr('ng-controller', 'CommentsCtrl');
$.when(angular.bootstrap($('.comments'), ['comments'])).done( function() {
console.log('COMMENTS: bootstrapped');
});
});
});
I hope you can use "ui-router" routing module.
Here is good tutorial for this http://www.ng-newsletter.com/posts/angular-ui-router.html

Categories

Resources