I am trying to unittest our angular directives which are implemented with external templates.
As far as I can find there are only two options:
use $httpBackend to respond with the template when requested in the directive
use the preprocessor created for Karma to fill the $templateCache
Number 1 is really not convenient and probably quite errorprone since we have to keep the actual template and the respond version in sync.
Number two is not an option since we are not in a position to install karma on our CI environment (TFS Online).
Have I missed something? Are there any other options?
Thanks,
Casper
Use the following process:
Download the templates using a tool (curl, grunt, gulp)
Concatenate the files
Move the concatenated file to your runtime template directory
Reference the concatenated file in the templateCache
Add the templateCache to your module
References
Feeding cURL HTML data to AngularJs
Gulp angular unit testing directive templateUrl
Angularjs: Number of HTTP requests when loading an HTML template?
Related
I have AngularJS project with more than 20 html templates (routes, modals).
I'm using grunt-angular-templates to split tempaltes in one file templates.js.
In my Angular project I'm using angular-route 1.2.25 for routing.
When I try to use template from templates.js file, browser crashes and not responding. There is any error on console.
The problem is only with html templates with Angular stuff (ng-switch, ng-show etc.)
When I load clean html it works.
I thing the problem is with compile the templates from $templateCache, but how o manage it?
Templates.js
...
$templateCache.put("name","HTML");
...
After long hours of search I found what's wrong.
In my solution I'm using Modal Boostrap for Angular.
grunt-angular-templates plugin don't compile this templates correctly. I just skip this files and all works.
I am using Angular UI router. I have many template calls like this:
var access = {
name: 'access',
templateUrl: 'app/access/partials/a1.html',
};
The page served by Access depends on the :content.
Is there a way that I could combine all these HTML files into one and pre-load the files so every action didn't involve another request? I realized I can put my HTML directly inside the template but can I combine the HTML from multiple templates into one file and have it all pre-loaded so it's ready when needed?
Is there a way that I could combine all these HTML files into one and pre-load the files so every action didn't involve another request?
Yes, by using html2js;
or, to be exact, a grunt/gulp plugin called, respectively, grunt-html2js / gulp-html2js
HOW IT WORKS
According to this grunt-html2js tutorial:
" html2js is a plugin (...) that parses all template files in your application and creates a javascript file that populates the $templateCache.
This is very useful trick to reduce the number of request your app needs to make to start the application.
It can also minify the html snippets saving some bandwitdh as well."
----------
According to the grunt-html2s Github repository:
"html2js converts a group of templates to JavaScript and assembles them into an Angular module that primes the cache directly when the module is loaded.
You can concatenate this module with your main application code so that Angular does not need to make any additional server requests to initialize the application."
----------
And according to me :)
What I like about html2js is that you don't need to change any of your angular code, but just configure gruntfile.js / gulpfile.js.
Your templateUrl files will then automagically be available in $templateCache.
So it does exactly what you wished for:
Combine all your templates into a module;
Write the JavaScript source for the module;
All you need to do is to specify the module as a dependency in your code.
Once the module is loaded, all your templates are available in the cache: no request needed!
EXAMPLES OF GRUNT / GULP CONFIG
grunt.initConfig({
html2js: {
options: {
base: 'app',
module: 'templates',
htmlmin: {
... many available options: see GitHub repo ...
}
},
main: {
src: ['app/**/*.html'],
dest: 'templates.js'
},
},
})
then just use the templates module as a dependency:
angular.module('myApp', [ 'templates']);
----------
Here is an example from the gulp-html2js GitHub repository:
gulp.task('scripts', function() {
gulp.src('fixtures/*.html')
.pipe(html2js({
outputModuleName: 'template-test',
useStrict: true
}))
.pipe(concat('template.js'))
.pipe(gulp.dest('./'))
})
TESTING
What's more, html2js is also a very good tool to test directives that use the templateUrl property.
FOR MORE INFORMATION
I came accross html2js after reading Joel Hooks' (Egghead instructor) book about automation, which I strongly recommend.
Watch a dedicated video about html2js in the pro section of the EggHead website.
Testing directives using the templateUrl property with Karma and karma-ng-html2js-preprocessor
NOTE
Technically, you could just use ng-html2js, without using Gulp or Grub; you could then use a command line like the following:
ng-html2js inputFile [outputFile] [-m moduleName] [--module-var ngModule]
However, as you would need to run the above command for each templateUrl file, Gulp/Grub automation seems to be a more efficient way to go.
DISCLAIMER
I have no particular interest or shares in the book/websites/tools I mentioned.
Note: I should also add, you also add this file to your html page:
<script src="path/to/templates.js"></script>
Why not use ng-include in your main html file to load all html's at once.
Something like this...
<div ng-repeat="template in templates">
<ng-include src="template.url"></ng-include>
</div>
So here templates is an array of objects which contains all the url's the other templates which you want to load at once in your main.html file.
Easy. Create them all as ng-template blocks:
<script type="text/ng-template" id="app/access/partials/a1.html">
Content of the template.
</script>
There is already a grunt-angular-templates grunt plugin specific to this angular task only. i have been using it for a while now. this plugin automatically caches your HTML templates using $templateCache in one file which you can add in your application.
grunt-angular-templates - https://www.npmjs.com/package/grunt-angular-templates
Use,
yourApp.run(['$templateCache', function($templateCache) {
$templateCache.removeAll();
}])
Your problem pointed in this site too,
http://javahow.net/questions/27321315/using-angulars-ui-router-how-can-we-make-sure-the-new-version-of-the-html-part
I'm looking at this sample Angular App.
In the main html file called [index.html][2], there is this line:
<div ng-include="'header.tpl.html'"></div>
However, there is not file header.tpl.html in the same directory.
How then does Angular know where to find this file?
The linked sample app is built using Grunt, so the file/folder structure of the built application differs from the one you see in the repository.
For example, the templates you are asking about, are collected by html2js (Grunt task) and compiled into a single JavaScript file containing code that adds all templates to $templateCache (causing them all to be included on app initialization instead of being lazily loaded when required). When the ng-include starts looking for files, its first step is looking into the $templateCache. Only when it cannot find the template there, it tries to load it from the server (and save it to $templateCache for subsequent uses).
See Gruntfile.js in the repository for build process details.
I have several modules that require some template partials to be loaded whenever the module is used. I am storing these files in a folder called partials inside each module subfolder. My starting point for my app is meanjs, and I am storing partials file are in public/modules//partials/*.html.
I have seen several ng-include and directive examples, but being new to AngularJS each sample I read confuses me further as to what is best practice / most AngularJS appropriate way to do this.
Store your partials whenever you wants.
To load them all use angular template cache.
Use Grunt or gulp to generate automatically. Personally I use gulp.
Here is my working example of one of my project.
install nodejs and npm
npm intall gulp -g
npm install gulp-angular-templatecache
create gulpfile.js
var templateCache = require('gulp-angular-templatecache'),
watch = require('gulp-watch');
gulp.task('generate', function () {
gulp.src('public/*/partials/*.html')
.pipe(templateCache('templates.js', {module: 'YOURMODULENAME', standalone: false}))
.pipe(gulp.dest('public/js'));
});
gulp.task('watch-partials', function () {
gulp.watch('public/*/partials/*.html', ['generate']);
});
then use it like this:
gulp generate - to regenerate partials
gulp watch-partials - watch file changes, if partials are changed it automatically run generate task for you. :)
One more thing, dont forget to include template.js in your html file
<script src="public/js/template.js"></script>
Every time you change your partial dont forget to regenerate your template cache.
You should take advantage of $templateCache. In your partials folder define the templates like this:
angular.module('yourTemplateModule', []).run('$templateCache', function ($templateCache) {
$templateCache.put('yourTemplate', '<div>...some HTML here...</div>');
}
Then create a module, named for example 'app.tpls', which has as dependencies all your template modules. Inject it as dependency to your main app module, probably located in meanjs and now you have your templates ready whenever you need them in your application. You retrieve them by calling:
$templateCache.get('yourTemplate');
I have set up my application based on this example
http://backbonetutorials.com/organizing-backbone-using-modules/
The thing that I now have more than 50 html files. It takes more than 5 seconds to load all files on first load. I know using node.js and require.js I can compress or minify the .js file and .css files but was wonder if there are any way we can compress all html templates into one file to speed up.
I'm about to face this very problem in my project and here's what I plan to do:
Write template loader function so that details of how templates are retrieved are encapsulated within. After that I only have to change one place in code when template handling logic changes.
At build time, compile my Handlebars.js templates into JS code. The process is described here.
Use R.js from require.js package to build single JS file from all compiled templates.
If you are using templates like described in that article (with require !text, _.template etc), then they will be compressed into JavaScript file as well. Give it a shot.
It doesn't make sense that 50 html files are loaded simultaneously into the browser, by right the require.js and node.js should be loaded once into the browser. Then ur index.html will select the html file amongst the 50 to append further as its content.