Jade templates for Angular directives - angularjs

In my MEAN app, I use jade as my template engine. My problem is, when I call an angular directive, jade code is not working but html code is working. My code is given below:
index.jade
div(ng-repeat="num in addDir")
admin-collection
directive.js
var formDir = angular.module("formDirective", []);
formDir.directive('adminCollection', function() {
return {
restrict: 'E',
transclude: true,
// call jade template url
templateUrl: '../_template/_formTemplate/_adminCollection.jade'
};
});
_adminCollection.jade
h1 from _adminCollection templateUrl
If I use jade format code in _adminCollection.jade, it just show a plain text, not text inside h1 tag
But following code is working:
directive.js
var formDir = angular.module("formDirective", []);
formDir.directive('adminCollection', function() {
return {
restrict: 'E',
transclude: true,
// call jade template url
templateUrl: '../_template/_formTemplate/_adminCollection.html'
};
});
_adminCollection.html code::
<h1> from _adminCollection templateUrl </h1>
How can I solve this problem?

Jade is a template engine. Browser has only built-in html parser, so it does not understand what jade code means and treats it as plaintext.
To make it work you need to convert it to html. You can use some task manager to do it. Two most popular task managers for node.js are gulp and grunt. Each of them has a working jade plugin which you can use right away.

Jade is something like less - it must be convert to another format, because browser can't understand that. When you use less, you have to transform it to css. And if you use jade - to html.
If you use grunt, you should look on it: https://github.com/gruntjs/grunt-contrib-jade
Otherwise you can check if your IDE can transform jade to html. For example PhpStorm can do this in automatic way.
Then in your directives you should specify path to html template, no jade.
You can use following directory structure:
app/
src/
js/
less/
jade/
dist/
templates/ <-- here you can put your htmls
styles/ <-- and here put css
js/ <-- if you want, you can put this minimalized app.js
that will contain all of your project,
see grunt-contrib-uglify for more info
EDIT: here is really great article about grunt: http://anthonydel.com/my-personal-gruntfile-for-front-end-experiments/ There is much more then you need, but maybe it will help you

.... Or you can to use webpack to do the work.
then you can load the template like this:
angular.module('app').component('myComponent', {
bindings: {},
template: require('./mytemplate.jade')()
});
You can to note that I'm invoking the returned function.

Another option is to keep the HTML templates in your DOM, but hidden:
div(ng-non-bindable, style="display: none")
#adminCollectionTemplate
div(ng-repeat="num in addDir")
admin-collection
#anotherTemplate
//- Alternatively, pull in the template from another file
include ./_formTemplate/_adminCollection.jade
and then use jQuery to fetch the HTML out of the DOM, and give it to angular:
formDir.directive('adminCollection', function() {
return {
restrict: 'E',
transclude: true,
// fetch template from DOM
template: $('#adminCollectionTemplate').html()
};
});
This will just work, without any Ajax or any task runners. But it will clutter up the DOM with templates that could otherwise be hidden away in the JS. And it is an extra step to place every new template into that div.
ng-non-bindable is needed to tell Angular to leave the template elements alone (don't manipulate them or bind to them), until their clones are actually used by the directive.

Related

angular ui-route state template with custom html tag

$stateProvider.state('abc', {
url: '/:id',
modal: true,
template: '<abc></abc>'
})
can I have custom html tag in template property?, e.g. 'abc', I was looking at someone else code but I don't understand how this works, I do have abc.html processed by gulp templatecache stuff. and it is loaded in a modal dialog correctly.
the file is at 'src/app/components/abc/abc.html', how come the template 'abc' knows which html to load? I suppose there must be a definition for 'abc' directive somewhere? but I can't find it.
I finally figured how it works, turns out the custom html tag is defined by a 'component' and there is some naming convention making this work.
http://blog.grossman.io/angular-1-component-based-architecture-2/
https://docs.angularjs.org/guide/component-router
Can I have custom html tag in template property
Yes, of course. Templates can use custom directives no matter how they are defined.
There should be an 'abc' directive somewhere in your module code or one of its dependencies.
See this SO question to be able to list the registered directives of your module and submodules in the console.
Yes, you can use custom html. UI Router provides you two choices, either you give the template or the templateUrl, which for the first one you have to write your html in a string literal, and latter you can set a html file location.
using template with string literal:
$stateProvider.state('abc', {
url: '/:id',
modal: true,
template: '<abc></abc>' // this is correct!
})
using templateUrl with html files.
$stateProvider.state('abc', {
url: '/:id',
modal: true,
templateUrl: '/path/to/abc.html' // if you have a file named `abc.html` in directory `path/to`, the template will be loaded
})

How to insert template in html using angular?

Scenario:-
I have html page rendering as angular template/view. Now there are big number of such template.
Now these templates has div in header part that is fixed through out the templates, now is there some-way that we can define one sub-template at one place and just insert that sub-template in all pages.
So that if there are any modification to be made, I will make in sub-template and that will be reflected in all the page.
Its like UserControls or Partials that we have in ASP.Net.
I am using AgularJS
Agreed that there are ui-routing for nested hosting but currently I am not looking for that.
Try
<div ng-include="path/to/template"></div>
you can create a seperate html file as template for header if it includes complex or considerable amount of elements. create a directive for this template and use it as an attribute/customTag or include it in your html using ng-include.
app.directive('header',function(){
return {
restrict: 'E', //'E': element /'A': attribute
templateUrl : 'templates/header.html'
}
});
use as attribute
<div header></div> // as Attribute
<header></header> // as element
if your header involves lot of functioning on it then you can also create a separate controller (which will act as a child controller) and add the controller to the above tags. such as
<header ng-controller="headerController"></header>
You probably want to use a directive template. This is a very simple directive with only the template information.
Eg:
<top-header></top-header>
module.directive('topHeader', function() {
return {
templateUrl: 'path',
// append
replace: true,
// attribute restriction
restrict: 'E'
}
});

Catching temlpateUrl path errors

I'm implementing a custom template inside a directive, like this:
.directive('card', function() {
return {
restrict: 'E',
replace: true,
templateUrl: function(element, attrs) {
return '/app/templates/' + attrs.cardtype + '.html';
}
};
});
The main template where the directive is generated looks like this:
<card ng-repeat="card in cards" cardtype="{{card.cardtype}}"></card>
Notice I'm using the "cardtype" attribute to select an appropriate template, and then assuming a template name in the directive.
This works fine as long as the cardtype attribute resolves to an html file in the template. However, if the file doesn't exist I get the error:
Error: [$compile:tpload] Failed to load template: /app/templates/{{card.cardtype}}.html
What's the best way to catch this error in order to render a default template?
I would try and ask $templateCache, whether this template exists. If you don't use template cache I highly recommend using it. You can set up a grunt task to scan all your .tpl.html files and set up a template-cache for use. In this way no real HTTP requests are going to get fired in order to fetch the templates.
For a nice example how to use templateCache see ng-boilerplate (ngbp)

Angular ng-include in Jade.

I'm trying to include a header, using ng-include from Angular into my Jade template:
doctype html
html(lang="en")
head
meta(charset='UTF-8')
meta(name='fragment', content='!')
base(href='/')
title Node Express Angular
link(rel='stylesheet', href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css')
link(rel='stylesheet', href='/css/syle.css')
body(ng-app='myApp')
ng-include(src='\'/partials/header.jade\'')
div.container
div.jumbotron.text-center
h1 Home Page
p This page is a draft in progress
script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.15/angular.min.js')
script(src='//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js')
script(src='/js/app.js')
The text in header.jade is the following:
nav.navbar.navbar-inverse(role='navigation')
ul.nav.navbar-nav.navbar-header
li
a(src='/home', class='navbar-brand') Home
li
a(src='/about') About
li
a(src='/login') Login
li
a(src='/register') Register
I have tried both ng-include(src='\'/partials/header.jade\'') and div(ng-include='\'/partials/header.jade\'')
In the Chrome developer console, the first one results in <!--ng-Include: undefined --> and the second: <!-- ng-Include: '/partials/header.jade' -->
Any clues?
Is there a specific reason why you're using Angular's ng-include instead of Jade's own include mechanism?
body(ng-app='myApp')
include partials/header
Reference form the the Jade docs.
I created an Angular directive to be rendered by JADE and then compiled by Angular to the given scope.... and it works!
btw,I'm using client-side Jade for browsers, the CDN is available here
for e.g:
html:
<ng-include src="'MyPageWithJadeScript.html'"></ng-include>
MyPageWithJadeScript.html:
<jade>tag#id.class jade text</jade>
angular:
app
.directive('jade',function($compile){
return{
transclude: true,
template: '<div ng-transclude></div>',
restrict: 'E',
link: function(scope, element){
element
.after(
$compile(
jade
.render(
element.html(),
{pretty:'\t'}
)
)(scope)
)
.remove();
}
};
});
Hope you find this useful
Refer to official doc ngInclude, using the code below
div(ng-include="'partials/header.jade'")
If you want to use ngInclude directive directly, use
ng-include(src="'partials/header.jade'")
Using express, I have the file user-description.jade inside of the views/ folder and to include it in another jade file I simple use the following expression:
div
include user-description.jade
Jade docs has other samples.

Angularjs load templates with directive

I have a directive that lets me insert a chat component. It loads a template as required.
mod.directive('chat', function () {
return {
replace: true,
templateUrl: '/tmpl/chat/chat',
}
})
But the problem is that the template needs additional includes:
.chat
.chatHeader(ng-include="'chatHeader'")
.chatLog(ng-include="'chatLog'")
Partials:
script( type="text/ng-template", id='chatLog')
.chatMsg(ng-include="'chatMsg'", ng-repeat='chatMsg in chatLog')
script( type="text/ng-template", id='chatHeader')
h3 Chat
How do I load the includes? I used to put the partials in the same file as base chat template but if I use replace: true that's no longer allowed.
What's the standard angular way to load included partials?
Using ng-include as you are is perfectly valid. The issue you are facing is likely because your template partial does not have exactly 1 root element. Here is a plunk with a working version of what you are describing: http://plnkr.co/wy1a3T1UdKOlBQXr9o22

Resources