Working Angularjs template cache on build and deployment - javascript

I am developing angular directives that used html template.
angular.module("app")
.directive("ticket", [function(){
return {
restrict: "E",
templateUrl: "app/ticket/ticket.html"
}
}])
This directive is working and I can change ticket.html content and run application to see changes.
But I read about $templateCache method to increase performance of big projects. And I can use grunt-angular-template to create all of template cache.
But I need to change my directive.
angular.module("app")
.directive("ticket", ["$templateCache",function($templateCache){
return {
restrict: "E",
template: $templateCache.get("app/ticket/ticket.html")
}
}])
Can I separate the build and deployment usage of template.
templateUrl: "app/ticket/ticket.html"
template: $templateCache.get("app/ticket/ticket.html")
I will select one of that ways. What is the professional approach for this?

You do not need to update this, you will automatically get it from the cache if you leave your code as it is, here you are just passing a template path to angular and angular gets it for you from the cache. $templateCache.get("app/ticket/ticket.html") is only needed if you want to load a template via js.

Related

How to correctly minify angularJS file

I have a simple angularjs directive and when I minify the file i get error because the variable names are changed
var app= angular.module('app',[]);
app.directive('directive',function(){
return {
restrict: 'EA',
scope: {},
replace: true,
link: function($scope, element, attributes){
$scope.name="test-test";
,
controller: function($scope,$attrs,$http){
},
templateUrl: 'directives/app/app.tpl.html'
}
});
the problem is $scope.name changes into a.name and angular doesn't recognize it.
I tried injecting $scope by trying something like
link: ['$scope',function($scope, element, attributes){
$scope.name="test-test";
}],
controller: ['$scope','$attrs','$http',function($scope,$attrs,$http){
}],
but I still get the same error of a.name when minified.
Directives link functions aren't injected. They're passed fixed set of parameters which are listed and comprehensively described in angular.js documentation. However this is not the case with controller. These are injected and should be annotated before minification. You can do it in at least 3 ways:
using array syntax like in your example
setting $inject property on controller function with value being array of names of injectables
annotating with ngAnnotate which will detect uses of angular injection and annotate it properly
The link function is not dependency injected. It uses only positional arguments so you don't have to use that explicit array naming. The controller one is fine I think.
At last, remember, you must write code for clarity. The explicit syntax is a bit too verbose, that's why most people choose to use ng-annotate instead. Ng-annotate is a compilation step which will convert the code to the explicit form before minification.

Dependency injection in Angular Components like directives

Here's one thing I'm used to do with angular directives
angular.module('app.directives').directive('login', ['$templateCache', function ($templateCache) {
return {
restrict: 'E',
template: $templateCache.get('directives/login/login.html'),
controller: 'LoginController as vm',
scope: true
};
}]);
I've grown very attached to using Template Cache to inject HTML content in my directive's template. Now with Angular 1.5 there's this new thing all the cool kids are using called component() which I'm giving a look to see if it's really good and I'm stuck at this very beginning part: how to inject things in the component itself (not in the controller)?
In this case you can see that I'm injecting into the login directive the $templateCache dependency. How would I rewrite this directive as a component? (keeping in mind my desire to use $templateCache over templateUrl)
Well, In Angular 1.5 components, template property can be a function and this function is injectable (documentation).
So, you can just use something like:
...
template: ['$templateCache', function ($templateCache) {
return $templateCache.get('directives/login/login.html')
}]
...
Few links from google search: one and two.
Hope it will help.
MaKCblMKo 's answer is right, but remember that AngularJS will check the templateCache first before going out to to retrieve the template. Therefore, you don't have to make this call in your directive or component.
angular.module('myApp', [])
.component('myComponent',{
templateUrl: 'yourGulpPattern'
})
.run(function($templateCache) {
$templateCache.put('yourGulpPattern', 'This is the content of the template');
});
https://jsfiddle.net/osbnoebe/6/

made angular scope available in Django TemplateResponse()

I am using Python/Django as back-end for framework and angular as front-end. At some point I am using TemplateResponse() in view function to get template response, this template includes HTML/CSS/JS/Angular code . TemplateResponse() can complie every other code but not angular bec angular scope is not available.
Here is sample code :
Django code
t = TemplateResponse(request,
'dynamic-content.html',
{'raw_html':raw_html,
'raw_css':raw_css,
'raw_js':raw_js,
'js_script':js_script,
'css_script':css_script,})
t.render()
Now I'll send t.content to angular which will include template response.
In angular I'll use directive to make angular scope available in the above template response .
<div dynamic="t.content"></div>
Directive :
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
But the time b/w providing angular scope to template response takes time.
Another issue is js gets compiled before angular scope available.
So either I have to make angular scope available in Template or stop js to get compile before angular.
What approach i should take regarding this . Please help.

Render speed issue when resuing a directive in AngularJS

I have the following simple base directive:
angular.module("base", [])
.directive("base", function() {
return {
restrict: "A",
scope: true,
controller: function($scope) {
this.setHeader = function(header) {
$scope.header = header;
}
this.setBody = function(body) {
$scope.body = body;
}
this.setFooter = function(footer) {
$scope.footer = footer;
}
},
templateUrl: "base.html"
}
});
I am passing data to this directive in the following way:
.directive("custom", function() {
return {
restrict: "E",
require: "^base",
scope: {
ngModel: "="
},
link: function($scope, $element, $attrs, baseCtrl) {
//Do something with the data or not...
baseCtrl.setHeader($scope.ngModel.header);
baseCtrl.setBody($scope.ngModel.body);
baseCtrl.setFooter($scope.ngModel.footer);
}
}
});
When I create a list of my custom directives, I notice the custom directives aren't rendering immediately. I have made a Plunker demonstrating this behavior. (You will see the list cells empty for a split second, then the directives will appear)
My goal behind this design is to reuse the template of the base directive and only pass in the data needed for display. In this simple example, $scope.data is exactly what I need to pass in but it may be the case some rules or manipulation need to happen first. Rather than have the controller which queried the data handle this, I wanted to pass it off into the directive, separating the concerns.
So my questions are:
Is there any way to make the directives render faster and avoid the flickering shown in the Plunker?
Is this a best practice for reusing directives with Angular?
The flickering is being caused by the async http request to the "base.html" file. Since the HTML for the base directive has to be loaded from the server, there will be a fraction of time where no content will be displayed.
In order to render the data, Angular will go though these 3 stages:
Fetch the HTML file/template from the server (no content will be displayed)
Compile the HTML template (the DOM is updated but the scope isn't yet linked)
Link the scope to the DOM/template (expected data is displayed)
Option 1 - Use the template attribute
Just replace the templateUrl: "base.html" for the direct HTML content:
//templateUrl: "base.html"
template: '<div class="base"><div class="header bottom-border"><h2>{{header}}</h2><div><div class="body bottom-border"><p>{{body}}</p></div><div class="footer">{{footer}}</div></div>',
You will notice that there won't be any flickering this time (check this plunker).
Option 2 - Pre-load template files
Angular has a built-in template cache ($templateCache) that it uses to check if any HTML template file/content has already been fetched from the server or not. If you populate that cache while the app is loading then Angular will not need to fetch the template to render the directive, it will read it directly from the cache.
You can use Angular's $templateRequest (if you are using the latest beta version of Angular) or $templateCache (for any version).
The difference is that $templateRequest automatically makes the HTTP GET request and stores the result in the $templateCache. On the other one you will have to do it manually, like this:
loadTemplate = function(tpl) {
$http.get(tpl, { cache : $templateCache })
.then(function(response) {
$templateCache.put(tpl, html);
return html;
});
};
loadTemplate('base.html');
Note however that this approach needs your app to have a "loading phase".
Regarding the best practices for reusing directives, you seem to be on the right path. The example is to simple to give any advices... Nevertheless, check the "Best practice" notes in this Angular "Creating Custom Directives" guide.
Edit
(my personal preferences regarding template vs templateUrl)
If the main goal is solely performance (i.e. page render speed) then template seems to be the best choice. Fetching one file will always be faster than fetching two... However, as the app grows, the need for a good structure is mandatory, and template files are one of the best practices when it comes to that.
Normally I follow this "rules":
If there are only a few lines of HTML in the template, then just use the template
If the HTML template will not be constantly changing over time (i.e. post structure, contact details, etc...), use template, otherwise (i.e. templates containing banners/ads) use templateUrl
If the app has a loading phase, use templateUrl with cache

angularjs routing behaviour of content and function calls

I'm new to Angular.js which is why I have a basic question regarding routing. I figured out how to create routes and inject specific .htmls by $routeProvider
var app = angular.module('test', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'routes/view2.html'
});
});
but what I really don't get is how content or function of view2.html are handled in Angular.
Lets take view2.html. It has a <p> with some text in a specific color. Nothing to special. But also it has a little slideshow which is called by $('slideshow').cycle() function.
All what happens is it displays me the <p> tag in a different color and no slideshow function is called on my rootsite of the app.
Could you give me some approach how to actually solve this?
Thanks
Just load required view and then compile it. During compilation Angular processes all directives in view.
If you want to do this proper(Angular) way you should put such code like $('slideshow').cycle() inside of directive. And then use it like
<div my-slideshow=""></div>
angular.module('myModule', [])
.directive('mySlideshow', [function () {
return {
restrict: 'A',
link: function (scope, element) {
element.cycle();
}
}
}]);
Directives documentation
Much more comprehensive documentation

Categories

Resources