<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8">
<title>Bootstrap-AngularJS Modal - Directive</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<script src="app.js"></script>
<script src="controller.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap-combined.min.css"
rel="stylesheet">
<style>
.modal-large {
width: 590px;
height: 650px;
left: 35%;
margin: -400px 0 0 -150px;
top: 50%;
}
</style>
</head>
<body ng-controller="Controller">
<div class="span12">
<h1>Bootstrap Modal</h1>
<p>The bootstrap modal directive allows you to open three different
types of modal windows:
</p>
<p>
<ul>
<li><b>Confirm</b></li>
<li><b>Alert</b></li>
<li><b>Dialog</b></li>
</ul>
</p>
<p>Confirm and alert get their content from referenced <b>div</b>
elements. These elements should contain the basic structure of a
typical modal window, analogous to the specs, which can be found in
Twitter Bootstrap. All tags are referenced via <b>modal="reference"</b>
and catching the <b>id</b> of the target element.
<br/>
The dialog modal is able to reference an URI to a view, which will be
loaded into the modal window. All <b>ng-click</b> events are mapped
through the directive and catchable in the parent controller. A modal
can be close by setting <b>$scope.closeModal</b>
</p>
<p>The properties to configure the modal are as follows:</p>
<p>
<ul>
<li><b>modal</b> configure the reference, or leave empty if dialog
should be loaded from url
</li>
<li><b>modal-type</b> defines the type of modal</li>
<li><b>modal-title</b> the title of the modal which is opened</li>
<li><b>modal-url</b> the url of a view which is referenced and
included in the modal
</li>
</ul>
</p>
<button class="btn btn-info" modal="confirmModal" modal-type="confirm"
modal-title="Confirm" modal-content="This is the modal content" modal-state="closeModal">Dialog - Confirm</button>
<div id="confirmModal">
<div class="modal-body">
<p>{{content}}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="confirm()">Confirm</a>
</div>
</div>
<button class="btn btn-warning" modal="alertModal" modal-type="confirm" modal-title="Alert">Dialog - Alert</button>
<div id="alertModal">
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<a href="" class="btn" ng-click="discard()">Discard</a>
<a href="" class="btn btn-primary" ng-click="ok()">Ok</a>
</div>
</div>
<button class="btn btn-danger" modal="" modal-type="dialog" modal-title="External no url">Dialog - Url Missing</button>
<button class="btn btn-success" modal="" modal-type="dialog" modal-title="Add Todo" modal-url="sample.html">Dialog</button>
<br/><br/>
<p>
The table below shows the todos added to the list
</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Due date</th>
<th>Estimate</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr ng-show="!todos.length">
<td colspan="4">No entries yet</td>
</tr>
<tr ng-repeat="todo in todos">
<td>{{todo.name}}</td>
<td>{{todo.date}}</td>
<td>{{todo.estimate}}</td>
<td>
<button class="btn btn-info" ng-click="edit($index)" modal="" modal-type="dialog" modal-title="Edit Todo" modal-url="sample.html"><i class="icon-white icon-pencil"></i></button>
<button class="btn btn-danger" ng-click="remove(todo)"><i class="icon-white icon-trash"></i></button>
</td>
</tr>
</tbody>
</table>
<pre>todos = {{todos | json}}</pre>
</div>
</body>
</html>
(function(angular) {
var modalDirective = angular.module('directive.modal', []);
modalDirective.templates = {
UrlNotDefined : '<div class="modal-body">'
+ '<h3>404 - Resource could not be found</h3>'
+ '<p>Specified URL <i>({{url}})</i> for Modal <strong>{{id}}</strong> could not be found.</p>'
+ '</div>'
+ '<div class="modal-footer">'
+ '<button type="button" class="btn btn-primary" ng-click="close()">Close</a>'
+ '</div>',
main : '<div style="position: absolute;" ng-class="{hide: !visible}">'
+ '<div class="modal-backdrop fade in">'
+ '</div>'
+ '<div class="modal" tabindex="-1" role="dialog" aria-labelledby="label" aria-hidden="true">'
+ '<div class="modal-header">'
+ '<button type="button" class="close" ng-click="close()">×</button>'
+ '<h1 id="label">{{title}}</h1>'
+ '</div>'
+ '</div>'
+ '</div>'
}
modalDirective.directive('modal', ['$rootScope', '$compile', '$timeout', '$http', function($rootScope, $compile, $timeout, $http) {
return {
restrict : 'A',
scope : '=',
compile: function compile(tElement, tAttrs, transclude) {
return {
post: function postLink(scope, iElement, iAttrs, controller) {
var modal = $(modalDirective.templates.main),
modalContainer = $('.modal', modal),
body = $('#' + iAttrs.modal),
error = $(modalDirective.templates.UrlNotDefined),
type = iAttrs.modalType,
url = iAttrs.modalUrl,
bodyContainer = 'body',
last = null;
scope.title = iAttrs.modalTitle;
scope.content = iAttrs.modalContent;
scope.visible = false;
body.css({ 'display' : 'none' });
if (type == 'dialog' && url !== undefined) {
$http.get(url).success(function (data) {
body = $(data);
}).error(function (error) {
scope.title = 'Errro loading contents';
body = $(error);
});
} else if(type == 'dialog' && url === undefined) {
scope.title = 'No url provided';
body = error;
}
iElement.click(function(event) {
open();
});
var open = function() {
modalContainer.append(body);
modal.appendTo(bodyContainer);
scope.visible = true;
body.css({ 'display' : 'block' });
scope.$apply($compile(modal)(scope));
last = event.timeStamp;
};
scope.close = function() {
scope.$emit('modal', 'close');
};
var closeModal = function() {
modal.remove();
};
scope.$on('modal', function(envelope, data) {
if (data === 'close')
closeModal();
});
$(bodyContainer).bind('keyup', function(event) {
if(event.which == 27) {
closeModal();
}
});
$(document).click(function(event) {
var target = $(event.target);
if(!target.is(".modal") && !target.parents().is(".modal")) {
if(last === event.timeStamp)
return;
closeModal();
}
});
}
};
}
};
}]);
})(window.angular);
var app = angular.module('myApp', ['directive.modal']);
app.controller('Controller', function($rootScope, $scope) {
$scope.todos = [];
$scope.todo = undefined;
$scope.confirm = function () {
console.log('confirm was clicked');
$scope.$broadcast('modal', 'close');
};
$scope.discard = function () {
console.log('discard was clicked');
$scope.todo = undefined;
$scope.$broadcast('modal', 'close');
};
$scope.ok = function () {
console.log('ok was clicked');
$scope.$broadcast('modal', 'close');
};
$scope.save = function () {
console.log('save was clicked');
if ($scope.todos.indexOf($scope.todo) === -1)
$scope.todos.push($scope.todo);
$scope.todo = undefined;
$scope.$broadcast('modal', 'close');
};
$scope.remove = function (todo) {
var index = $scope.todos.indexOf(todo);
$scope.todos.splice(index, 1);
};
$scope.edit = function (index) {
$scope.todo = $scope.todos[index];
};
var modalObject = {
modal : '',
modalType : 'dialog',
modalUrl : 'sample.html',
modalTitle : 'This is a sample title'
};
$scope.modalObject = modalObject;
});
app.controller('ChildController', function($scope) {
$scope.initDialog = function () {
if ($scope.$parent.$parent.todo !== undefined) {
$scope.todo = $scope.$parent.$parent.todo;
} else {
$scope.todo = {};
}
$scope.$parent.$parent.todo = $scope.todo;
};
});
<div class="modal-body" ng-controller="ChildController" ng-init="initDialog()">
<form>
<label>Todo title</label>
<input type="text" class="input-medium" placeholder="Add Todo.." ng-model="todo.name">
<label>Todo date</label>
<input type="text" class="input-medium" placeholder="Add Todo.." ng-model="todo.date">
<label>Todo estimate</label>
<input type="text" class="input-medium" placeholder="Add Todo.." ng-model="todo.estimate">
</form>
</div>
<div class="modal-footer">
<a href="" class="btn" ng-click="discard()">Discard</a>
<a href="" class="btn btn-primary" ng-click="save()">Save changes</a>
</div>
</div>