Html template with Angular - angularjs

How to use Html template instead of Jade in Angular Application.
layout.html:
<body>
{% block content %}{% endblock %}
<h1>Hello!! whats up from layout</h1>
</body>
index.html:
{% extends 'includes/layout.html' %}
{% block content %}
<section> <h1>hello</h1></section>
{% endblock %}
Server.js
app.set('views',__dirname + '/server/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine','html');
app.get('*',function(req,res){
res.render('index');
});
But i am not getting output as expected, below is the snap of what i am getting in the browser.
{% extends 'includes/layout.html' %} {% block content %}
hello
{% endblock %}
I don't understand what i am missing.

Looks like you're not utilizing the proper view engine. See this article by Rod Dodson. The crucial line is:
app.set('view engine', 'ejs');
You have:
app.set('view engine','html');
This means express is simply rendering your EJS templates as raw HTML. Make sure Express understands which view engine you want to use, and you should be set.

I have a nice little working MEAN stack application, and i believe it can be a good base for you to set up express/node app with AngularJS HTML templates.
Even if your configured view engine in app.js(server.js or whatever name you call it) might be jade or EJS, Expressjs is quite flexible,you can still serve the HTML partials using AngualrJS routes.
So my base index.html looks something like this:
NOTE: there are ways to efficiently load JS files, but since it's a small To-Do App. so i am not going for it.
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MEAN To Do Application </title>
<link href="vendor/flat-ui/css/vendor/bootstrap.min.css" rel="stylesheet">
<link href="vendor/flat-ui/css/flat-ui.css" rel="stylesheet">
</head>
<body ng-controller="AppCtrl">
<div ng-include="'app/header.tpl.html'"></div>
<div ng-view class="container-fluid"></div>
<script src="vendor/flat-ui/js/vendor/jquery.min.js"></script>
<script src="vendor/flat-ui/js/vendor/html5shiv.js"></script>
<script src="vendor/flat-ui/js/vendor/respond.min.js"></script>
<script src="vendor/flat-ui/js/vendor/video.js"></script>
<script src="vendor/flat-ui/js/flat-ui.min.js"></script>
<script type="text/javascript" src="vendor/angular-full/angular.min.js"></script>
<script src="vendor/angular-full/angular-resource.min.js"></script>
<script src="vendor/angular-full/angular-route.min.js"></script>
<script src="/socket.io/socket.io.js"> </script>
<script src="common/socketservice.js"></script>
<script src="app/app.js"></script>
<script src="app/meetups/meetups.js"></script>
</body>
</html>
Then here comes by Angular routes config(refer):
angular.module('meetups',['ngResource'],['$routeProvider',function($routeProvider){
$routeProvider
.when('/',{
templateUrl: 'app/meetups/list.tpl.html',
controller: 'MeetupsController'
})
.when('/create',{
templateUrl : 'app/meetups/create.tpl.html',
controller: 'MeetupsController'
})
.when('/:id',{
templateUrl: 'app/meetups/details.tpl.html',
controller: 'MeetupsController'
})
.when('/:id/edit',{
templateUrl: 'app/meetups/edit.tpl.html',
controller: 'MeetupsController'
})
.otherwise({redirectTo: '/'})
;
}]);
I hope i answered your question.

This is a clientside solution. Just FYI.
You may set any other character for angular's interpolate symbol:
app.config(function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[').endSymbol(']]');
});
(but it's may hurt - ide with angular support didn't recognize your symbol)
The best practice of binding - is use ngBind whenever it's possible (instead of {{ }} expresions):
<span ng-bind="myVal"></span>
It is preferable to use ngBind instead of {{ expression }} if a template is momentarily displayed by the browser in its raw state before Angular compiles it. Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading.
(from docs)
instead of
<span>{{myVal}}</span>

Related

Angular 8 hybrid app not recognizes AngularJS components

I started developing a hybrid application. So I have done th folllowing steps:
add Angular 8 dependencies
add polyfills.ts
remove ng-app attribute from my root index.html
do a manual bootstrap of AngularJs app
How looks my Angular init module:
#NgModule({
imports: [
BrowserModule,
UpgradeModule
]
})
export class HubAngularModule {
ngDoBootstrap() {
}
}
platformBrowserDynamic().bootstrapModule(HubAngularModule)
.then(platformRef => {
console.log("Bootstrapping in Hybrid mode with Angular & AngularJS");
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, ['myAngularJsModule']);
});
How looks my index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="dist/index.bundle.js"></script> <!--Webpack bundle-->
<link rel="stylesheet" href="dist/styles.css"/>
</head>
<body>
<div layout="column" layout-align="" ng-cloak>
<main-header></main-header> <!--AngularJS header component-->
<console-menu></console-menu> <!--AngularJS menu component-->
<md-content ui-view="main"></md-content> <!--AngularJS root ui-view-->
</div>
</body>
</html>
main-header, console-menu - are AngularJS components. Of course that configuration works well when ng-app is presented.
What I expect. Hybrid app starts just like old AngularJS app and I'm able to see login page, start page etc.
What I actually got. AngularJS app is actually bootstrapping. I can see method app.module().run(...) executes. But no component loads so I see only a blank page.
After a several hours of experiments I have found a soultion.
I decided to check whether the manual bootstrap of the AngularJS will work:
angular.element(document)
.ready(() => {
angular.bootstrap(document.body, ['myAngularJsModule']);
});
And it had failed. Even if no Angular 8 present. So the reason it fails to start is a location of <script> tags with my webpack bundles. It located in <head> but should be located in <body> after all the app markup.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div layout="column" layout-align="" ng-cloak>
<main-header></main-header> <!--AngularJS header component-->
<console-menu></console-menu> <!--AngularJS menu component-->
<md-content ui-view="main"></md-content> <!--AngularJS root ui-view-->
</div>
<script src="dist/index.bundle.js"></script> <!--Webpack bundle-->
<link rel="stylesheet" href="dist/styles.css"/>
</body>
</html>
It is so dumb, but exactly that dumb thing like this make the biggest headache sometimes. And what disappointed me me the most not a single migration tutorial tells nothing about that detail!
Have you upgraded your angularJS components to make them work in Angular ?

Open a new Site in angular

I had a Single Page Application developed in angular-js and i need to open a printside under a new url. At present, printtext.html loads its content but on the inside of the index.html. What i want is to load the content of the printtext.html alone without any Content from the index.html. Basically if i click on the link in my index.html i just want to see in the browser the text printtext. And not something like Some headertext which is curretnly the case. Is that possible or do i break the SPA rules? My Main goal is to create a Printsite where i just see the content without any header or footer information. Or should i user ng-hide for this?
I am not including the logic here, but if required will provide.
Index.html
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Myapp</title>
<script src="libs/js/angular.js"></script>
<script src="libs/js/angular-route.js"></script>
<script src="js/app.js"></script>
</head>
<body>
<h1> Some headertext </h1>
<ng-view></ng-view>
</body>
app.js
var app = angular.module('myapp', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/text', {
templateUrl: "template/text.html"
})
.when('/print', { //actually the parameter is /print/:object but i left the logic out here
templateUrl: "Print/printtext.html"
})
}])
text.html
<p> Some text </p>
<a ng-href="#!/print">Print </a> <!-- The right link would be something like #!/print/marc -->
printtext.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html ng-app="myapp">
<head><title>
Printview
</title>
<script src="../libs/js/angular.js"></script>
<script src="../libs/js/angular-route.js"></script>
<script src="../js/app.js"></script>
<body>
<p>printtext</p>
</body>
</html>
You directly use target = "_blank" in your anchor tag.
<p> Some text </p>
<a ng-href="#!/print" target="_blank">Print </a> <!-- The right link would be something like #!/print/marc -->
Otherwise, you can create a dynamically custom directive in angular.
custom directive generally uses to set target according to a dynamic condition.
<p> Some text </p>
<a ng-href="#!/print" ng-attr-target="_blank">Print </a> <!-- The right link would be something like #!/print/marc -->
<a ng-attr-target="_blank">
...
</a>
ng-attr-xyz lets you dynamically create #xyz, and if the value is undefined no attribute is created.

How to conditionally load a different index.html in angularjs

I'm building an angular app, and using a standard index.html file:
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.css">
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="https://code.jquery.com/jquery-2.1.3.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
What I'd like to do is have a different index.html or a "home.html" file loaded, if a user is not logged into the app. The home.html will be a single static page marketing site with it's own design and css/js. I'd like that page to be served from the '/' route, and other routes to be handled by the angular app.
How would I dynamically load a different starting html file?
The logic to route to another html should be placed in your login module. It could be not related with Angularjs
There are some code to redirect another page from outside or inside of angular app
$location.url('/RouteTo/index');
$location.url('/index');
$window.location.href="http://www.domain.com/home";
window.location = "http://www.domain.com/home";
you can get your host for app $window.location.host

Variable not being displayed in DOM, yet ng-repeat works

I was setting up a very basic AngularJS + Ionic app, and encountered a weird case where despite the ng-repeat working properly (e.g repeating the correct number of times), the variables weren't rendered on the DOM. Additionally, I saw this weird behavior only happening in my local app, but working properly on an exact copy on Plunker.
On app.js I have:
angular.module('sleepExpertChatApp', [
'ionic',
])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('peoplelist', {
url: '/peoplelist',
templateUrl: 'templates/people-list.html',
controller: 'PeopleListCtrl'
});
$urlRouterProvider.otherwise('/peoplelist');
})
.controller('PeopleListCtrl', function($scope){
$scope.obj = {}
$scope.test = "Mytestvar"
$scope.obj.people = [{name:"leon"},{name:"jeff"},{name:"leon"}];
console.log($scope.obj);
});
And my html:
<!DOCTYPE html>
<html ng-app="sleepExpertChatApp">
<head>
<script src="http://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
<script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.1/angularfire.min.js"></script>
<script src="/static/chat/main.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.ionicframework.com/1.0.0/css/ionic.min.css">
</head>
<body>
<ion-nav-view></ion-nav-view>
<script id="templates/people-list.html" type="text/ng-template">
<ion-view id="userMessagesView"
view-title="People">
afsdf
<ion-content>
<div ng-repeat="person in obj.people">
<div class="item">
{{person.name}}
</div>
</div>
</ion-content>
</ion-view>
</script>
</body>
</html>
This is the Plunker: http://plnkr.co/edit/UV3AJoEFpUeE45DkVv9A
Locally, the simple ng-repeat does produce the right number of elements, but when trying to evaluate the expression to display the variables, nothing is shown. See the below screenshot and notice that there are 3 divs with class item, as expected, but they have no name.
Any ideas what could be going wrong in this seemingly trivial set up?
Ah! I didn't realize I was serving the HTML from a Django server, and so Django's template rendering engine was clashing with AngularJS's.
Simply wrapping my HTML with Django's {% verbatim %} tag fixed my problem.

deep linking, page reloads, angular js

I have a table which should be filtered depending on the url.
This is my module::
angular.module('myApp', ['pipelibservice']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/pipes/:pipeID', {templateUrl: 'partials/wizard.html', controller: PipeListCtrl});
}]);
In my template I have a list with a href that should filter the table:
<li ng-repeat="pipe in pipes">
<a href='#/pipes/{{ pipe.code }}'>{{ pipe.code }} - {{pipe.title_en}}</a>
</li>
This is my index.html
<!doctype html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>Google Phone Gallery</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="css/app.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/0.7.2/angular-strap.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
<script src="lib/angular/angular-resource.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
Problem is, the entire page reloads when I hit the link. I only want the url to change so my table is filtered. How do I fix so the page is not reloaded?
Update:
I've narrowed it down to the rest API call. If i replace the rest call with hardcoded values (from the orginal rest-call) then it works. Any idea what can be wrong?
you cant normally use $route and not refresh the page. but in your case i would just use a filter http://docs.angularjs.org/api/ng.filter:filter
<li ng-repeat="pipe in pipes | filter: pipeID">
<a href='#/pipes/{{ pipe.code }}'>{{ pipe.code }} - {{pipe.title_en}}</a>
</li>
dont forget to put in ctrl $scope.pipeID = $routeParams.pipeID
P.S. i wrote a post explaning a bit simpler Ben Nadels idea (which is awesome) and its a way to use $route without refreshing http://bresleveloper.blogspot.co.il/2013/08/breslevelopers-angularjs-tutorial-basic_20.html
the point is that using $route with templateUrl and/or controller creates new instances of the controller and view, and by ur description u dont want it. so u can drop the templateUrl controller and send a custom parameter and in the app use ngSwitch to switch ngInclude and u manage it all with 1 controller
As per ngHref documentation, you should use ng-click to prevent the page reload:
{{ pipe.code }} - {{pipe.title_en}}
You would need to create the goToPipe function in your controller, with something like:
$scope.goToPipe = function (pipe_code) {
$location.path("/pipe/" + pipe_code);
};
The only solution I've found to this problem so far is this:
http://www.bennadel.com/blog/2441-Nested-Views-Routing-And-Deep-Linking-With-AngularJS.htm
Take a look at their demo:
http://bennadel.github.io/AngularJS-Routing/#/pets/cats/10/medical-history
Notice the tabs BACKGROUND, DIET, MEDICAL HISTORY and how the do not refresh the page.
However this solution is very complex and involves and employing a lot of non-native to angular stuff.
I'm still looking to find a simpler solution to this simple problem.

Resources