Okay so I am trying to learn how to create a modular angular app, but I don't really know how it would look. Based on my code what would I need to do to make it modular? My app is pretty small but I still want to try and get the idea down as for how to create a modular app so that I can just do that from the beginning the next time I create a web app. I didn't include the css as it seems irrelevant for this question. Help would be greatly apprciated.
index.html
<!DOCTYPE html>
<html>
<head>
<header>To do App</header>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>To do App</title>
<script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"> </script>
<script type='text/javascript' src="//use.edgefonts.net/vast-shadow:n4:all.js"></script>
<script type='text/javascript' src="//use.edgefonts.net/vast-shadow:n4:all;megrim.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script type='text/javascript' src="js/index.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div ng-app="demoApp">
<script type="text/ng-template" id="partials/edit-form.html">
<div ng-show="todo.editMode">
<input ng-model="todo.text" />
<button ng-click="save(todo)">save</button>
</div>
</script>
<div class="todo-wrapper" ng-controller="todoCtrl">
<h2>You have <span class="emphasis">{{getTotalTodos()}}</span> tasks</h2>
<input class="search-input" type="text" ng-model="searchText" placeholder="enter search term" />
<ul>
<li ng-repeat="todo in todos | filter: searchText">
<span>{{todo.text}}: {{todo.date_created}}</span>
<div ng-include="'partials/edit-form.html'"></div>
<button class="clear-btn" ng-click="removeTask(todo)">Remove</button>
<button class="clear-btn" ng-click="editTask(todo)">Edit</button>
</li>
</ul>
<form>
<input class="add-input" placeholder="task name" type="text" ng-model="text" ng-model-instant />
<button class="add-btn" ng-click="addTask()"><h2>Add</h2></button>
</form>
</div>
</body>
</html>
index.js
angular.module('demoApp', [])
.controller('todoCtrl', TodoCtrl);
function TodoCtrl($scope) {
$scope.todos = [{
id: 1,
text: 'Mow the lawn',
selected: false
}, {
id: 2,
text: 'Wash the car',
selected: false
}];
$scope.id = $scope.todos.length + 1; //later create an uuid
$scope.getTotalTodos = function () {
return $scope.todos.length;
};
$scope.addTask = function () {
$scope.todos.push({
editMode: false,
text: $scope.text,
id: $scope.id,
date_created: Date.now,
selected: false
});
$scope.text = '';
$scope.id = '';
};
$scope.removeTask = function (todo) {
/*$scope.todos = _.filter($scope.todos, function (todo) {
return !todo.selected;
});*/
$scope.todos.pop(todo);
//update server now with ngResource...
};
$scope.showDetails = function (task_id) {
var found = $filter('filter')($scope.todos, {
id: task_id
}, true);
if (found.length) {
$scope.selected = JSON.stringify(found[0]);
} else {
$scope.selected = 'Not found';
}
}
$scope.editTask = function(todo) {
todo.editMode = true;
console.log(todo);
};
$scope.save = function(todo) {
todo.editMode = false;
// update data at server now too. $scope.todos is up-to-date
}
$scope.updateTask = function (task_id) {
// search $scope.todos for the item to update
var indexOfTask;
for (var i = 0; i < $scope.todos.length; i++) {
if ($scope.todos[i].id === $scope.id) indexOfTask = i;
$scope.todos[i] = todo;
$scope.todos.push();
$scope.text = '';
$scope.id = '';
}
// update the todo
};
}
Essentially just make a new file for every angular whatever (factory, controller, directive, etc.)
I use this syntax
angular.module('myapp.functionName.type', [])
.type('functionName',);
Then in your app.js, in your case index.js
angular.module('myapp', ['myapp.functionName.type', ... ]) ;
Related
I have a simple angular controller to post a new name and display the name on the page.
The problem is I cant see the name and the rest of the details to show in the scope ....
Any idea how to fix this and why its not working ?
HTML
<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Angular Base64 Upload Demo</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script type="text/javascript" src="//cdn.rawgit.com/adonespitogo/angular-base64-upload/master/src/angular-base64-upload.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div ng-controller="UpLoadImage">
<div ng-repeat="step in stepsModel">
<img class="thumb" ng-src="{{step}}"/>
</div>
<label for="file">Select File</label>
<input type='file' name='file' base-sixty-four-input required onload='onLoad' maxsize='600'
accept='image/*' ng-model-instant onchange='angular.element(this).scope().imageUpload(this)'/>
</div>
<div ng-controller="PostData">
{{items.c_name}}
<form ng-submit="sendPost()">
<input ng-model="newName"/>
<button type="submit">Send Data</button>
</form>
</div>
</body>
</html>
App.js
angular.module('myApp', ['naif.base64'])
.controller('UpLoadImage', function ($scope, $http, $window, $rootScope) {
$scope.imageUpload = function (element) {
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(element.files[0]);
};
$scope.imageIsLoaded = function (e) {
$scope.$apply(function () {
$scope.stepsModel.push(e.target.result);
});
$scope.onLoad = function (e, reader, file, fileList, fileOjects, fileObj) {
alert('image uploaded');
};
};
$scope.stepsModel = [];
})
.controller('PostData', function ($scope, $http) {
$scope.items = {
c_name: "Campaign name here",
max_slots: 5,
slots: [
{
slot_id: 1,
base_image: "base 64 image"
}
]
};
$scope.newName = "Enter name";
$scope.sendPost = function() {
var data = $.param({
json: JSON.stringify({
c_name: $scope.newName
})
});
$http.post("/echo/json/", data).success(function(data, status) {
$scope.items = data;
})
}
});
You missed ng-model property in base-sixty-four-input directive input:
angular.module('myApp', ['naif.base64'])
.controller('UpLoadImage', function ($scope, $http, $window, $rootScope) {
$scope.imageUpload = function (element) {
var reader = new FileReader();
reader.onload = $scope.imageIsLoaded;
reader.readAsDataURL(element.files[0]);
};
$scope.imageIsLoaded = function (e) {
$scope.$apply(function () {
$scope.stepsModel.push(e.target.result);
});
$scope.onLoad = function (e, reader, file, fileList, fileOjects, fileObj) {
alert('image uploaded');
};
};
$scope.stepsModel = [];
})
.controller('PostData', function ($scope, $http) {
$scope.items = {
c_name: "Campaign name here",
max_slots: 5,
slots: [
{
slot_id: 1,
base_image: "base 64 image"
}
]
};
$scope.newName = "Enter name";
$scope.sendPost = function() {
var data = $.param({
json: JSON.stringify({
c_name: $scope.newName
})
});
$http.post("/echo/json/", data).success(function(data, status) {
$scope.items = data;
})
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Angular Base64 Upload Demo</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script type="text/javascript" src="//cdn.rawgit.com/adonespitogo/angular-base64-upload/master/src/angular-base64-upload.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div ng-controller="UpLoadImage">
<div ng-repeat="step in stepsModel">
<img class="thumb" ng-src="{{step}}"/>
</div>
<label for="file">Select File</label>
<input ng-model="file" type='file' name='file' base-sixty-four-input required onload='onLoad' maxsize='600'
accept='image/*' ng-model-instant onchange='angular.element(this).scope().imageUpload(this)'/>
</div>
<div ng-controller="PostData">
{{items.c_name}}
<form ng-submit="sendPost()">
<input ng-model="newName"/>
<button type="submit">Send Data</button>
</form>
</div>
</body>
</html>
Are you sure property c_name exists on the data returned by the $http.post ? . Add a console log to print what you really get. You also have to ensure there is no error by setting an error callback. I also suggest to give a name other than data for the result (res instead of data for example):
var data = {}; // There is already a variable named data here
$http.post("/echo/json/", data).success(function(res, status) {
$scope.items = res;
console.log("$scope.items: ", $scope.items);
}, function() { console.log("There is an error"); })
Add ng-modal to input where you used base-sixty-four-input directive.
Add cdn path of jquery.
How to prevent this angularjs child component from updating its parent component? In the code below, the instant I update the form in the modal, it updates the parent model as well. This prevents the "cancel" button from working properly.
Here's the plunker showing the issue.
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2017.1.118/styles/kendo.common.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2017.1.118/styles/kendo.bootstrap.min.css" />
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<script src="//code.jquery.com/jquery-1.12.4.js"></script>
<script src="//code.angularjs.org/1.5.8/angular.js"></script>
<script src="//kendo.cdn.telerik.com/2017.1.118/js/kendo.all.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.js"></script>
<script id="documents-template" type="text/ng-template">
<button id="openDetails" name="openDetails" ng-click="model.openDetails(1)" class="btn btn-default">Open Details</button>
<pre>{{ model | json }}</pre>
</script>
<script id="details-template" type="text/ng-template">
<div class="modal-body">
<label>Name To Edit</label>
<input ng-model="model.document.title">
<br>
<label>Value To Edit</label>
<input ng-model="model.document.fileName">
<br>
<button class="btn btn-success" type="button" ng-click="model.save()">Save Changes</button>
<button class="btn btn-default" type="button" ng-click="model.cancel()">Cancel</button>
</div>
<pre>{{ model | json }}</pre>
</script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="app">
<documents-component></documents-component>
</div>
</body>
</html>
script.js
console.clear();
function documentController($uibModal, TransactionFactory) {
var model = this;
model.transaction = TransactionFactory;
model.openDetails = function(id) {
$uibModal.open({
animation: true,
component: 'detailsComponent',
resolve: {
document: function () {
return model.transaction.documents[id - 1];
}
}
}).result.then(function(result) {
console.log("Save result was:", result);
}, function(reason) {
console.log("Dimissed reason was:", reason);
});
};
}
function detailsController() {
var model = this;
model.document = model.resolve.document;
console.log("model.document", model.document);
model.save = function() {
console.log("saved was clicked. Passing back:", model.document);
model.modalInstance.close(model.document);
};
model.cancel = function() {
model.modalInstance.dismiss("cancel");
};
}
var app = angular.module("app", ["kendo.directives", "ngAnimate", "ui.bootstrap"]);
app.factory('TransactionFactory', function() {
var doc1 = { id:1, title: "Doc1", fileName: "Doc1.pdf" }
var doc2 = { id:2, title: "Doc2", fileName: "Doc2.pdf" }
var doc3 = { id:3, title: "Doc3", fileName: "Doc3.pdf" }
var doc4 = { id:4, title: "Doc4", fileName: "Doc4.pdf" }
var dummyData = [doc1, doc2, doc3, doc4];
console.log("dummyData:", dummyData);
return {
documents: dummyData
};
});
app.component("documentsComponent", {
template: $("#documents-template").html(),
controllerAs: "model",
controller: ["$uibModal", "TransactionFactory", documentController]
});
app.component("detailsComponent", {
template: $("#details-template").html(),
bindings: {
modalInstance: "<",
resolve: '<'
},
controllerAs: "model",
controller: [detailsController]
});
Tried a few changes... basically passing a copy of the required object and only saving (assigning) it when the Save Changes button is clicked.
Your function should be:
model.openDetails = function(id) {
$uibModal.open({
animation: true,
component: 'detailsComponent',
resolve: {
document: function () {
return angular.copy( model.transaction.documents[id - 1] );
}
}
}).result.then(function(result) {
console.log("Save result was:", result);
model.transaction.documents[id - 1] = result ;
}, function(reason) {
console.log("Dimissed reason was:", reason);
});
Try it out
The problem is that in both components you're using reference to the same object with data. So when you edit data in modal you actually edit original object with data which is used also by parent component. Solution is to pass copy of object to your modal.
Refer to the updated plunker https://plnkr.co/edit/cvR8i883Q1ZlPPTA8Ryk?p=preview. you need to pass a copy of object.
function detailsController() {
var model = this;
model.document = angular.copy(model.resolve.document);
console.log("model.document", model.document);
model.save = function() {
console.log("saved was clicked. Passing back:", model.document);
model.modalInstance.close(model.document);
};
model.cancel = function() {
model.modalInstance.dismiss("cancel");
};
}
I cant save the uploaded file name and format through json value. I'm getting response but I can't save and update in json file sample_data.json. its showing an error:
TypeError: a.push is not a function
Please help me.
Error:
Thanks in advance.
Html
<!DOCTYPE html >
<html ng-app='uploadfiles'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Upload files</title>
</head>
<body ng-controller="uploadCtrl">
<div class="container" >
<form >
<input type="file" ng-file-model="files" multiple model="model" />
<button type="button" ng-click="upload()">Upload</button>
</form>
<p ng-repeat="file in files">
{{file.name}}
</p>
<div id="result">
<p>{{msg}}</p>
</div>
</div>
<script src="lib/angular.min.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-resource.min.js"></script>
<script src="app/app.js" type="text/javascript"></script>
<script src="app/controller.js" type="text/javascript"></script>
<script src="app/directives.js" type="text/javascript"></script>
</body>
</html>
app.js
var uploadApp = angular.module('uploadfiles',['ngResource', 'myAppServices']);
controller.js
uploadApp.controller('uploadCtrl',['$scope','uploaddata', function($scope, uploaddata, $http) {
$scope.files =[];
$scope.upload=function(){
uploaddata.save($scope.files, function(data) {
$scope.msg ='file saved';
});
};
}]);
var myAppServices = angular.module('myAppServices', ['ngResource']);
myAppServices.factory('uploaddata', ['$resource',
function($resource) {
return $resource('../uploadfiles/temp/sample_data.json', {}, {});
}
]);
Directive.js
uploadApp.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var value = {
// File Name
name: item.name,
//File Size
size: item.size,
type: item.type,
//File URL to view
url: URL.createObjectURL(item),
// File Input Value
_file: item
};
values.push(value);
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);
by default, resource expects an object as result, not an array;
try setting the resource option: "isArray: true"
I am having hard time to pass this error:
Uncaught Error: [$injector:modulerr]
when I am trying to make an authentication app with AngularJS. I put the code in plunker.
Here are my codes:
1- app.js
"use strict";
(function() {
var app = angular.module('loginApp', ['AuthService', 'Session']);
app.constant('appSettings', {
title:'Authentication Application',
version:'1.0'
});
app.constant('AUTH_EVENTS', {
loginSuccess: 'auth-login-success',
loginFailed: 'auth-login-failed',
logoutSuccess: 'auth-logout-success',
sessionTimeout: 'auth-session-timeout',
notAuthenticated: 'auth-not-authenticated',
notAuthorized: 'auth-not-authorized'
});
app.constant('USER_ROLES', {
all: '*',
admin: 'admin',
editor: 'editor',
guest: 'guest'
});
app.controller('footerController', function($scope, appSettings){
$scope.appSettings = appSettings;
});
}());
2 - applicationcontroller.js
"use strict";
(function() {
var applicationcontroller = function ($scope, USER_ROLES, AuthService) {
$scope.currentUser = null;
$scope.userRoles = USER_ROLES;
$scope.isAuthorized = AuthService.isAuthorized;
$scope.setCurrentUser = function (user) {
$scope.currentUser = user;
};
};
applicationcontroller.$inject = ['$scope', 'USER_ROLES', 'AuthService'];
angular.module('loginApp')
.controller('applicationcontroller', applicationcontroller);
}());
3- logincontroller.js
"use strict";
(function() {
var logincontroller = function ($scope, $rootScope, AUTH_EVENTS, AuthService) {
$scope.credentials = {
username: '',
password: ''
};
$scope.login = function(credentials){
AuthService.login(credentials).then(function(user){
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
$scope.setCurrentUser(user);
}, function(error){
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
};
};
logincontroller.$inject = ['$scope', '$rootScope', 'AUTH_EVENTS', 'AuthService'];
angular.module('loginApp')
.controller('logincontroller', logincontroller);
}());
4- authservice.js
"use strict";
(function(){
var AuthService = function($http, Session){
var authService = {};
authService.login = function (credentials) {
return $http
.post('/login', credentials)
.then(function (res) {
Session.create(res.data.id, res.data.user.id,
res.data.user.role);
return res.data.user;
});
};
authService.isAuthenticated = function () {
return !!Session.userId;
};
authService.isAuthorized = function (authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (authService.isAuthenticated() &&
authorizedRoles.indexOf(Session.userRole) !== -1);
};
return authService;
};
AuthService.$inject = ['$http', 'Session'];
angular.module('loginApp').factory('AuthService', AuthService);
}());
5- session.js
"use strict";
(function(){
var Session = function(){
this.create = function (sessionId, userId, userRole) {
this.id = sessionId;
this.userId = userId;
this.userRole = userRole;
};
this.destroy = function () {
this.id = null;
this.userId = null;
this.userRole = null;
};
};
angular.module('loginApp').service('Session', Session);
}());
6- index.html
<!DOCTYPE html>
<html data-ng-app="loginApp" lang="en">
<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>Authentication</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link href="css/main.css" rel="stylesheet">
</head>
<body ng-controller="applicationcontroller">
<div class="container">
<div class="jumbotron">
<form name="loginForm" ng-controller="logincontroller" ng-submit="login(credentials)" novalidate>
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" ng-model="credentials.username" class="form-control">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" ng-model="credentials.password" class="form-control">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<hr class="color-violet">
<footer class="text-center" data-ng-controller="footerController"> MADE WITH <i class="fa fa-heart color-violet"></i> BY <span class="color-violet">ALAN SABERI</span>. FIND THIS ON <span class="color-violet">GITHUB</span><div>Version: {{appSettings.version}}</div></footer>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="vendor/bootstrap.min.js"></script>
<script src="vendor/angular.min.js"></script>
<script arc="js/services/authservice.js"></script>
<script arc="js/services/session.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/applicationcontroller.js"></script>
<script src="js/controllers/logincontroller.js"></script>
</body>
</html>
First of all you have a typo when referencing your script files
<script arc="js/services/authservice.js"></script>
<script arc="js/services/session.js"></script>
Should be
<script src="js/services/authservice.js"></script>
<script src="js/services/session.js"></script>
Second -> Your AuthService and Session are not new modules, they are being registered in the same loginApp module based on your code. So you don't inject them into your loginApp module.
Change
var app = angular.module('loginApp', ['AuthService', 'Session']);
to this
var app = angular.module('loginApp', []);
Third -> You are loading your service script files before loading your app.js, remember app.js is where you are first defining your loginApp module that you are using to assign your services, so change your script load order to be this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="bootstrap.min.js"></script>
<script src="angular.min.js"></script>
<script src="app.js"></script>
<script src="session.js"></script>
<script src="authservice.js"></script>
<script src="applicationcontroller.js"></script>
<script src="logincontroller.js"></script>
Here's your plnkr that's forked and working : http://plnkr.co/edit/5BEIsVxwt8sKwr4HA8Eq?p=preview
I am new to angular and I am trying to build my first directive, but it's not rendering inside my HTML.
Here is my HTML page : the directive is called at the bottom of the HTML
<!DOCTYPE html>
<html ng-app="store">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-controller="storeController as store">
<ul class="list-group">
<li class="list-group-item" ng-repeat="product in store.product">
<h3 >
<product-name></product-name>
</h3>
</li>
</ul>
</body>
</html>
And here is my app.js :
(function(){
var app = angular.module("store",[]);
var gem = [
{
name: "Dodec",
price: 2.95,
canPurchase: true,
soldOut: false,
reviews: []
},
{
name: "Panta",
price: 20.4,
canPurchase: true,
soldOut: false,
reviews: []
}
];
app.controller("storeController",function(){
this.product = gem;
});
app.controller("tabController",function($scope){
$scope.tab = 1;
$scope.SetTab = function(value){
$scope.tab = value;
};
$scope.IsSet = function(value){
return value === $scope.tab;
}
});
app.controller("ReviewController", function($scope){
$scope.review = "";
$scope.addReview = function(product){
product.reviews.push($scope.review);
$scope.review = "";
};
});
app.directive("productName",function(){
return {
restrict : "E",
templateUrl : "product-name.html"
};
});
})();
notice the directive at the end.
And finally here is my product-name.html file :
{{product.name}}
<em class="pull-right"> {{product.price | currency}}</em>
What did I do wrong? why is the directive not behaving like it should?
Thanks
In product-name.html, AngularJS directive templates must have one root element.
I wrapped the html in divs in this plnkr.
<div>
{{product.name}}
<em class="pull-right"> {{product.price | currency}}</em>
</div>
The problem was with my server, I downloaded the http server from here https://github.com/nodeapps/http-server then started it and the directive shows up now.