minifying js file containing routing - angularjs

I am minifying an angular project through gulp.This project contains index.html,css,libraries,app.js(Angular module containing routing layer+controllers) and views.
I could easily minify+concat all js files,libraries and css files into one bundle file.HTML files were also easily minified but the problem is i have routing in my app.js which render templateUrl like
.state('dashboard.home', {
url: '/home',
templateUrl: 'app/views/dashboard/home.html'
})
Now,beacause of this routing i cannot minify+concat all html files into one.because each route renders one view with its file name while there will be only one file named bundle.html.
Here,I need a guideline about how to handle this situation.
Thanks Regards

I use the gulp-ng-template for this:
gulpfile.js:
var ngTemplate = require('gulp-ng-template');
....
gulp.task('templates', function () {
return gulp.src(['view1.html', 'view2.html'])
.pipe(ngTemplate({filePath: 'js/tpl.js'}))
.pipe(gulp.dest('test'));
});
ngTemplate combines your views and puts them into the single file js/tpl.js that will look like this:
angular.module('ngTemplates').run(['$templateCache', function($templateCache) {
$templateCache.put('view1.html', '<div class="test">A</div>\n');
$templateCache.put('view2.html', '<div class="test">\n <span>B</span>\n</div>\n');
}]);
Now all you need is to include this file into your index.html. Your views will be available to the angular compiler at their original paths. You don't need to include your original html views into project any more.
You can add this file js/tpl.js to your index.html manually or by using ng-html-replace.

Instead of concatenating all templates into one html file you should use $templateCache angular provider and convert all of your html templates into JavaScript code. By using templateCache you can put all of your teplates into one file and it will work perfectly with routing mechanism. Try this gulp module Gulp ng templates

Related

Typescript directive html template in gulp

I am looking at switching from Grunt to Gulp and I have everything I need working except for one thing.
When I was using Grunt, I used grunt-ts and it had a very nice feature for dealing with html templates for angular directives. https://www.npmjs.com/package/grunt-ts#html
It takes my directive template html file and creates a .ts file for it. This fits very nicely into our build process since all .ts-files are compiled and concat:ed to one file.
Now, when I use gulp-typescript(https://www.npmjs.com/package/gulp-typescript) I no longer have this feature.
Is there a way to recreate the functionality from grunt-ts to the Gulp workflow?
Basically, what I need to do is:
Watch all *.tpl.html files in a specified directory. [No problem]
When file is changed, minify the html contents (using gulp-minify-html) in the file and add the minified html content to a new file(in the same directory) with this file content:
module [directivename].tpl{
export var html ='MINIFIEDHTML';
}
Any suggestions on how I can accomplish this? Or is there a better way to do this?
`
I believe gulp-angular-templatecache is what you need.
var templateCache = require('gulp-angular-templatecache');
gulp.task('default', function () {
return gulp.src('templates/**/*.html')
.pipe(templateCache())
.pipe(gulp.dest('public'));
});
You can see how John papa does that from here

ng-boilerPlate with a custom directive

I am just starting out with AngularJS. I decided to go with ng-BoilerPlate as a structure.
I am currently stuck on creating a small custom directive.
What I did was the following :
I created an html file for the directive under src/app/login/sso/facebook-button.html.
This contains just regular code you need for a directive.
<a href="#" class="btn btn-lg btn-block omb_btn-facebook">
<i class="fa fa-facebook visible-xs"></i>
<span class="hidden-xs">Facebook</span>
</a>
In this same directory I also created the javascript file needed for this directive "ssoDirective.js".
app.directive('facebookButton', function() {
return {
restrict : 'E',
templateUrl : 'facebook-button.html'
};
});
Finally I just used the template in a login.tpl.html file (which works no problem without this template).
<facebook-button><facebook-button>
Now when I grunt this code (just the normal grunt config of ng-boilerPlate) I get the following error in Chrome :
GET http://localhost:63342/app/login/sso/facebook-button.html 404 (Not Found)angular.js:8632
Error: [$compile:tpload] Failed to load template: /app/login/sso/facebook-button.html
I understand why this error is arrising. When I look into the build directory the facebook-button.html file just isn't there anywhere. Using grep I can also not find the contents of this file anywhere in this directory.
So grunt clearly skips this file while building.
So the question is. How do you create a very simple directive like this in ng-boilerPlate. Where do you place the .html for a directive so it gets included in the grunt build of ng-boilerPlate, and what templateUrl you specify so it gets found.
The templates in ngbp will be merged into one file during the build process (actually two separate files, templates-app.js for the app-modules and templates-common.js for common reusables). This process done by html2js task configured in Gruntfile.js.
In build.config.js you can specify which files where to merge. By default all files match src/common/**/*.tpl.html pattern goes to templates-common.js and files match src/app/**/*.tpl.html merged into templates-app.js. You can also add your own rules but don't forget to configure Gruntfile.js as well!
If you really want to use explicit template definition (so the template will not be merged into build/templates-app or build/templates-common.js) one solution is to use the template property on your directive and provide the template inline. A better way to achieve the same is to use $templateCache to include template.
Refering to the documentation of $templateCache
First you must configure the run() section of your module as the following:
app.run(function($templateCache) {
$templateCache.put('facebook-button.html', 'Content of facebook-button.html');
});
Now you can use the standard templateUrl way to include facebook-button.html into your directive!
app.directive('facebookButton', function() {
return {
restrict : 'E',
templateUrl : 'facebook-button.html'
};
});
You can get cleaner code if you separate the function and give just reference to run()
(function(){
'use strict'
angular
.module('app',[...])
.run(Template);
.directive('facebookButton',Directive);
function Directive(){
return {
restrict : 'E',
templateUrl : 'facebook-button.html'
};
}
function Template($templateCache) {
$templateCache.put('facebook-button.html',
'...'+
'Content of facebook-button.html'+
'...'
);
}
})();

AngularJS load in controllers that are in separate files

app.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/demo', {
templateUrl : 'assets/pages/home.html'
})
// route for the sport page
.when('/sport', {
templateUrl : 'assets/pages/sport/home.html',
controller : 'sportController'
});
// route for the sport page
.when('/television', {
templateUrl : 'assets/pages/television/home.html',
controller : 'televisionController'
});
});
I have sportControllerin a file called SportCtrl.js and televisionController in a file called TvCtrl.js, how would I be able to load this into my view while using Routing?
You should correctly add your controller in app namespace and Angular does all things themselves.
For example, working structure for project:
Load Angular, dependencies.
Load your application initializer, configs.
Load other stuff like controllers, directives, services, filters.
Example of controller code:
app.controller('sportController', ['$scope', function($scope){
}])
BTW, for Angular file name means nothing.
You are trying to do a lazy loading of javascript files. This is not an Angular functionality, you have 3 solutions:
use requireJs to load files on-the-fly.
include all your javascript files in html
concatenate all the javascript files in only one file.
I prefer not to use requireJS to prevent one more inclusion and configuration :-)

AngularJS - How to modularize a directive + template combination?

Here's the situation. I have a directive, that depends on a templateUrl.
The directive looks something like this:
angular.module('foo')
.directive('bar', function(){
return {
restrict: 'E',
replace: true,
templateUrl: '/foo/bar.html',
controller: 'fooController',
require: '^ngModel',
scope: {
onSuccess: '&'
}
};
});
This directive is part of one of my applications, and it's important that it stays part of the application. However, I'd also like to use the same directive in other projects, and currently I'm using bower to pull down the repository into my other projects. However, this directive will break because the templateUrl will be incorrect. Bower clones down my entire project, and the actual path of the template, at best, will need to be this in my other project:
/lib/public/foo/bar.html
How do other people manage this?
I've never liked using template strings for templating due to issues with maintainability. I prototype html very quickly so I opt for a grunt task that reads my files and processes them into a single $templateCache js file.
Solution
Grunt Angular Templates
Grunt build task to concatenate & register your AngularJS templates in
the $templateCache
// within my Gruntfile.js
grunt.initConfig({
ngtemplates: {
'angular-my-directives': {
src: 'views/**/*.html', // where my view files are
dest: 'src/templates.js' // single file of $templateCache
}
}
// ...
});
generates something like: ./src/templates.js which preserves my folder structure:
angular.module('angular-my-directives').run(['$templateCache', function($templateCache) {
$templateCache.put('views/directives/my-download.html',
"<form name=\"myDownloadForm\" ng-submit=\"submit()\" novalidate>\n" +
"</form>"
);
}]);
Now in my directive I can simply use templateUrl: 'views/directives/my-download.html' and it will use the $templateCache.
Finally I used grunt-contrib-concat to combine my files for easy loading.
Checkout "Grunt concat + uglify with sourcemaps" (or leave a better link in comments) to learn about how to concat + uglify (aka min) js files into a single "dist" file.
If working on your own custom bower package..
Be sure to commit the concatenated (aka built) files to the package repo so your package consumers can simply include my-concat-package.js or my-concat-package.min.js
Angular directives have templateUrl and template properties. template receives a HTML string. It's not a perfect solution, because you need to put HTML into your JS. But it is a common pattern for library creators to put the HTML string directly on template property, so they can wrap their module into a single file.
You may want make that templateUrl-to-template a build step of you lib.
Take a look on Angular Bootstrap Bower Repo.
One solution to this, and my personally preferred solution to this, is to put the template into $templateCache in a Module.run function. That way you never have to worry about the url referring to the wrong thing--you can give it any arbitrary identifying url you want--and it will never require an http request to fetch that template, to boot.
In your-directive project:
Create all template with xyz.tpl.html file name, and put into your-directive dir with all js code. All templateUrl looks like
templateUrl: '/template/my.tpl.html'
In app project:
Create a gulp/grunt task in your project for copy all *.tpl.html file into /template/ dir from bower_components (default).
e.g.:
// copy template files
gulp.task('copy-tpl', function() {
return gulp.src([
config.dirs.src.bower_components + '/**/*.tpl.html'
])
.pipe(flatten())
.pipe(gulp.dest(config.dirs.build.tpl));
});
Important!
The /template dir is a convention (as js, css, etc).
You can do this with gulp using gulp-angular-templatecache.
You directive would look like so:
angular.module('foo').directive('bar', function($templateCache){
return {
restrict: 'E',
replace: true,
template: '$templateCache.get('bar.html')',
controller: 'fooController',
require: '^ngModel',
scope: {
onSuccess: '&'
}
};
});
And your gulpfile.js would look like this:
var gulp = require('gulp'),
addTemplates = require('gulp-angular-templatecache');
gulp.task('default', function() {
gulp.src('templatesDir/**/*.html')
.pipe(addTemplates('templateFile.js', {module: 'foo' }))
.pipe(gulp.dest('dist'));
});
This produces the file 'templateFile.js' in your dist folder which then can be packaged with your directive file in your bower.json.
I already gave an answer using grunt to build your html files into $templateCache file, but I've since switched to gulp, so anyone looking to follow same process but using gulp, checkout gulp-angular-templatecache

Adding scripts on route config

Upon learning Angular Route Styles, It's easier to apply different styles on different templates.
Since it makes it so dynamic, I was wondering if there's a library to append scripts file(s) dynamically within the route configuration on a particular template like Angular Route Styles for stylesheet?
More like this (focusing more on js: "app/controller/template.js")
$routeProvider.when("/",
{
templateUrl: "template.html",
controller: "TemplateCtrl",
css: "css/template.css",
js: "app/controller/template.js"
});
I was planning to write an external js file for the controller of the template. Thus of course, removing the property controller: "TemplateCtrl" on the configuration file. But this would make things more easier for code management.

Resources