UI Bootstrap
Bootstrap components written in pure AngularJS by the AngularUI Team
Getting started
Dependencies
This repository contains a set of native AngularJS directives based on Twitter Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's JavaScript is required. The only required dependencies are:
- AngularJS (minimal version 1.0.4 or 1.1.2)
- Bootstrap CSS
Files to download
Build files for all directives are distributed in several flavours: minified for production usage, un-minified for development, with or without templates. All the options are described and can be downloaded from here.
Alternativelly, if you are only interested in a subset of directives, you can create your own build.
Whichever method you choose the good news that the overall size of a download is very small: <20kB for all directives (~5kB with gzip compression!)
Installation
As soon as you've got all the files downloaded and included in your page you just need to declare
a dependency on the ui.bootstrap
module:
angular.module('myModule', ['ui.bootstrap']);
You can fork one of the plunkers from this page to see a working example of what is described here.
Collapse (ui.bootstrap.collapse)
AngularJS version of twitter's collapse plugin. Provides a simple way to hide and show an element with a css transition
<div ng-controller="CollapseDemoCtrl">
<button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
<hr>
<div collapse="isCollapsed">
<div class="well well-large">Some content</div>
</div>
</div>
function CollapseDemoCtrl($scope) {
$scope.isCollapsed = false;
}
Accordion (ui.bootstrap.accordion)
The body of the accordion group grows to fit the contents
The accordion directive builds on top of the collapse directive to provide a list of items, with collapsible bodies that are collapsed or expanded by clicking on the item's header.
We can control whether expanding an item will cause the other items to close, using the close-others
attribute on accordion.
The body of each accordion group is transcluded in to the body of the collapsible element.
<div ng-controller="AccordionDemoCtrl">
<label class="checkbox">
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
<accordion close-others="oneAtATime">
<accordion-group heading="Static Header">
This content is straight in the template.
</accordion-group>
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
<accordion-group heading="Dynamic Body Content">
<p>The body of the accordion group grows to fit the contents</p>
<button class="btn btn-small" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</accordion-group>
</accordion>
</div>
function AccordionDemoCtrl($scope) {
$scope.oneAtATime = true;
$scope.groups = [
{
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1"
},
{
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2"
}
];
$scope.items = ['Item 1', 'Item 2', 'Item 3'];
$scope.addItem = function() {
var newItemNo = $scope.items.length + 1;
$scope.items.push('Item ' + newItemNo);
};
}
Alert (ui.bootstrap.alert)
Alert is an AngularJS-version of bootstrap's alert.
This directive can be used to generate alerts from the dynamic model data (using the ng-repeat directive);
The presence of the "close" attribute determines if a close button is displayed
<div ng-controller="AlertDemoCtrl">
<alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
<button class='btn' ng-click="addAlert()">Add Alert</button>
</div>
function AlertDemoCtrl($scope) {
$scope.alerts = [
{ type: 'error', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success', msg: 'Well done! You successfully read this important alert message.' }
];
$scope.addAlert = function() {
$scope.alerts.push({msg: "Another alert!"});
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
}
Carousel (ui.bootstrap.carousel)
Slide {{$index}}
{{slide.text}}
- {{$index}}: {{slide.text}}
Enter a negative number to stop the interval.
Carousel creates a carousel similar to bootstrap's image carousel.
Use a <carousel>
element with <slide>
elements inside it. It will automatically cycle through the slides at a given rate, and a current-index variable will be kept in sync with the currently visible slide.
<div ng-controller="CarouselDemoCtrl">
<carousel interval="myInterval">
<slide ng-repeat="slide in slides" active="slide.active">
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{$index}}</h4>
<p>{{slide.text}}</p>
</div>
</slide>
</carousel>
<div class="row-fluid">
<div class="span6">
<ul>
<li ng-repeat="slide in slides">
<button class="btn btn-mini" ng-class="{'btn-info': !slide.active, 'btn-success': slide.active}" ng-disabled="slide.active" ng-click="slide.active = true">select</button>
{{$index}}: {{slide.text}}
</li>
</ul>
<a class="btn" ng-click="addSlide()">Add Slide</a>
</div>
<div class="span6">
Interval, in milliseconds: <input type="number" ng-model="myInterval">
<br />Enter a negative number to stop the interval.
</div>
</div>
</div>
function CarouselDemoCtrl($scope) {
$scope.myInterval = 5000;
$scope.slides = [
{image: 'http://placekitten.com/200/200',text: 'Kitten.'},
{image: 'http://placekitten.com/225/200',text: 'Kitty!'},
{image: 'http://placekitten.com/250/200',text: 'Cat.'},
{image: 'http://placekitten.com/275/200',text: 'Feline!'}
];
$scope.addSlide = function() {
$scope.slides.push({
image: 'http://placekitten.com/'+(200+25*Math.floor(Math.random()*4))+'/200',
text: ['More','Extra','Lots of','Surplus'][Math.floor(Math.random()*4)] + ' ' +
['Cats', 'Kittys', 'Felines', 'Cutes'][Math.floor(Math.random()*4)]
});
};
}
Dialog (ui.bootstrap.dialog)
Change options at will and press the open dialog button below!
Alternatively open a simple message box:
The $dialog
service allows you to open dialogs and message boxes from within your controllers. Very useful in case loading dialog content in the DOM up-front is tedious or not desired.
Creating custom dialogs is straightforward: create a partial view, its controller and reference them when using the service. Generic message boxes (title, message and buttons) are also provided for your convenience.
For more information, see the dialog readme on github.
<div ng-controller="DialogDemoCtrl">
<div class="row-fluid">
<div class="span6">
<label class="checkbox"><input type=checkbox ng-model="opts.backdrop">Show backdrop</label>
<label class="checkbox"><input type=checkbox ng-model="opts.dialogFade">Fade modal dialog </label>
<label class="checkbox"><input type=checkbox ng-disabled="!opts.backdrop" ng-model="opts.backdropFade">Fade Backdrop</label>
<hr>
<label class="checkbox"><input type=checkbox ng-model="opts.keyboard">Close on Escape</label>
<label class="checkbox"><input type=checkbox ng-disabled="!opts.backdrop" ng-model="opts.backdropClick">Close on backdrop click</label>
</div>
<div class="span6">
<p>Change options at will and press the open dialog button below!</p>
<p><button class="btn btn-primary" ng-click="openDialog()">Open Dialog</button></p>
<p>Alternatively open a simple message box:</p>
<p><button class="btn btn-primary" ng-click="openMessageBox()">Open Message Box</button></p>
</div>
</div>
</div>
function DialogDemoCtrl($scope, $dialog){
// Inlined template for demo
var t = '<div class="modal-header">'+
'<h1>This is the title</h1>'+
'</div>'+
'<div class="modal-body">'+
'<p>Enter a value to pass to <code>close</code> as the result: <input ng-model="result" /></p>'+
'</div>'+
'<div class="modal-footer">'+
'<button ng-click="close(result)" class="btn btn-primary" >Close</button>'+
'</div>';
$scope.opts = {
backdrop: true,
keyboard: true,
backdropClick: true,
template: t, // OR: templateUrl: 'path/to/view.html',
controller: 'TestDialogController'
};
$scope.openDialog = function(){
var d = $dialog.dialog($scope.opts);
d.open().then(function(result){
if(result)
{
alert('dialog closed with result: ' + result);
}
});
};
$scope.openMessageBox = function(){
var title = 'This is a message box';
var msg = 'This is the content of the message box';
var btns = [{result:'cancel', label: 'Cancel'}, {result:'ok', label: 'OK', cssClass: 'btn-primary'}];
$dialog.messageBox(title, msg, btns)
.open()
.then(function(result){
alert('dialog closed with result: ' + result);
});
};
}
// the dialog is injected in the specified controller
function TestDialogController($scope, dialog){
$scope.close = function(result){
dialog.close(result);
};
}
Dropdown Toggle (ui.bootstrap.dropdownToggle)
DropdownToggle is a simple directive which will toggle a dropdown link on click. Simply put it on the <a>
tag of the toggler-element, and it will find the nearest dropdown menu and toggle it when the <a dropdown-toggle>
is clicked.
<li class="dropdown" ng-controller="DropdownCtrl">
<a class="dropdown-toggle">
Click me for a dropdown, yo!
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in items">
<a>{{choice}}</a>
</li>
</ul>
</li>
function DropdownCtrl($scope) {
$scope.items = [
"The first choice!",
"And another choice for you.",
"but wait! A third!"
];
}
Modal (ui.bootstrap.modal)
I'm a modal!
- {{item}}
modal
is a directive that reuses $dialog
service to provide simple creation of modals that are already in your DOM without the hassle of creating partial views and controllers.
The directive shares $dialog
global options.
For more information, see the dialog readme on github.
<div ng-controller="ModalDemoCtrl">
<button class="btn" ng-click="open()">Open me!</button>
<div modal="shouldBeOpen" close="close()" options="opts">
<div class="modal-header">
<h4>I'm a modal!</h4>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">{{item}}</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-warning cancel" ng-click="close()">Cancel</button>
</div>
</div>
</div>
var ModalDemoCtrl = function ($scope) {
$scope.open = function () {
$scope.shouldBeOpen = true;
};
$scope.close = function () {
$scope.closeMsg = 'I was closed at: ' + new Date();
$scope.shouldBeOpen = false;
};
$scope.items = ['item1', 'item2'];
$scope.opts = {
backdropFade: true,
dialogFade:true
};
};
Pagination (ui.bootstrap.pagination)
A lightweight pagination directive that is focused on ... providing pagination!
It will take care of visualising a pagination bar. Additionally it will make sure that the state (enabled / disabled) of the Previous / Next and First / Last buttons (if exist) is maintained correctly.
It also provides optional attribute max-size to limit the size of pagination bar.
<div ng-controller="PaginationDemoCtrl">
<pagination num-pages="noOfPages" current-page="currentPage"></pagination>
<pagination num-pages="noOfPages" current-page="currentPage" class="pagination-small" previous-text="«" next-text="»"></pagination>
<pagination boundary-links="true" num-pages="noOfPages" current-page="currentPage" max-size="maxSize"></pagination>
<pagination num-pages="noOfPages" current-page="currentPage" max-size="maxSize"></pagination>
<pagination direction-links="false" num-pages="noOfPages" current-page="currentPage"></pagination>
<button class="btn" ng-click="setPage(3)">Set current page to: 3</button>
The selected page no: {{currentPage}}
</div>
var PaginationDemoCtrl = function ($scope) {
$scope.noOfPages = 7;
$scope.currentPage = 4;
$scope.maxSize = 5;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
};
Tooltip (ui.bootstrap.tooltip)
Pellentesque {{dynamicTooltipText}}, sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in aliquam. Tincidunt lobortis feugiat vivamus at left eget arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur right nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas bottom pharetra convallis posuere morbi leo urna, fading at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus delayed turpis massa tincidunt dui ut.
I can even contain HTML. Check me out!
Or use custom triggers, like focus:
A lightweight, extensible directive for fancy tooltip creation. The tooltip directive supports multiple placements, optional transition animation, and more.
There are two versions of the tooltip: tooltip
and tooltip-html-unsafe
. The
former takes text only and will escape any HTML provided. The latter takes
whatever HTML is provided and displays it in a tooltip; it called "unsafe"
because the HTML is not sanitized. The user is responsible for ensuring the
content is safe to put into the DOM!
The tooltip directives provide several optional attributes to control how they will display:
tooltip-placement
: Where to place it? Defaults to "top", but also accepts "bottom", "left", or "right".tooltip-animation
: Should it fade in and out? Defaults to "true".tooltip-popup-delay
: For how long should the user have to have the mouse over the element before the tooltip shows (in milliseconds)? Defaults to 0.tooltip-trigger
: What should trigger a show of the tooltip?
The tooltip directives require the $position
service.
Triggers
The following show triggers are supported out of the box, along with their provided hide triggers:
mouseenter
:mouseleave
click
:click
focus
:blur
For any non-supported value, the trigger will be used to both show and hide the tooltip.
<div ng-controller="TooltipDemoCtrl">
<div class="well">
<div>Dynamic Tooltip Text: <input type="text" ng-model="dynamicTooltipText"></div>
<div>Dynamic Tooltip Popup Text: <input type="text" ng-model="dynamicTooltip"></div>
<p>
Pellentesque <a><span tooltip="{{dynamicTooltip}}">{{dynamicTooltipText}}</span></a>,
sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in
aliquam. Tincidunt lobortis feugiat vivamus at
<a><span tooltip-placement="left" tooltip="On the Left!">left</span></a> eget
arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur
<a><span tooltip-placement="right" tooltip="On the Right!">right</span></a>
nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
<a><span tooltip-placement="bottom" tooltip="On the Bottom!">bottom</span></a>
pharetra convallis posuere morbi leo urna,
<a><span tooltip-animation="false" tooltip="I don't fade. :-(">fading</span></a>
at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
<a><span tooltip-popup-delay='1000' tooltip='appears with delay'>delayed</span></a> turpis massa tincidunt dui ut.
</p>
<p>
I can even contain HTML. <a><span tooltip-html-unsafe="{{htmlTooltip}}">Check me out!</span></a>
</p>
<p>
Or use custom triggers, like focus:
<input type="text" value="Click me!"
tooltip="See? Now click away..."
tooltip-trigger="focus"
tooltip-placement="right" />
</p>
</div>
</div>
var TooltipDemoCtrl = function ($scope) {
$scope.dynamicTooltip = "Hello, World!";
$scope.dynamicTooltipText = "dynamic";
$scope.htmlTooltip = "I've been made <b>bold</b>!";
};
Popover (ui.bootstrap.popover)
Dynamic
Positional
Triggers
Other
A lightweight, extensible directive for fancy popover creation. The popover directive supports multiple placements, optional transition animation, and more.
Like the Twitter Bootstrap jQuery plugin, the popover requires the tooltip module.
The popover directives provides several optional attributes to control how it will display:
popover-title
: A string to display as a fancy title.popover-placement
: Where to place it? Defaults to "top", but also accepts "bottom", "left", or "right".popover-animation
: Should it fade in and out? Defaults to "true".popover-popup-delay
: For how long should the user have to have the mouse over the element before the popover shows (in milliseconds)? Defaults to 0.popover-trigger
: What should trigger the show of the popover? See thetooltip
directive for supported values.
The popover directives require the $position
service.
<div ng-controller="PopoverDemoCtrl">
<div class="well">
<div>
<h4>Dynamic</h4>
<div>Dynamic Popover : <input type="text" ng-model="dynamicPopoverText"></div>
<div>Dynamic Popover Popup Text: <input type="text" ng-model="dynamicPopover"></div>
<div>Dynamic Popover Popup Title: <input type="text" ng-model="dynamicPopoverTitle"></div>
<div><button popover="{{dynamicPopover}}" popover-title="{{dynamicPopoverTitle}}" class="btn">{{dynamicPopoverText}}</button></div>
</div>
<div>
<h4>Positional</h4>
<button popover-placement="top" popover="On the Top!" class="btn">Top</button>
<button popover-placement="left" popover="On the Left!" class="btn">Left</button>
<button popover-placement="right" popover="On the Right!" class="btn">Right</button>
<button popover-placement="bottom" popover="On the Bottom!" class="btn">Bottom</button>
</div>
<div>
<h4>Triggers</h4>
<button popover="I appeared on mouse enter!" popover-trigger="mouseenter" class="btn">Mouseenter</button>
<input type="text" value="Click me!"
popover="I appeared on focus! Click away and I'll vanish..."
popover-trigger="focus" />
</div>
<div>
<h4>Other</h4>
<button Popover-animation="true" popover="I fade in and out!" class="btn">fading</button>
<button popover="I have a title!" popover-title="The title." class="btn">title</button>
</div>
</div>
</div>
var PopoverDemoCtrl = function ($scope) {
$scope.dynamicPopover = "Hello, World!";
$scope.dynamicPopoverText = "dynamic";
$scope.dynamicPopoverTitle = "Title";
};
Progressbar (ui.bootstrap.progressbar)
Static
Dynamic
Value: {{dynamic}}No animation Object (changes type based on value)
Stacked
Array values with automatic typesValue: {{stackedArray}}Objects
Value: {{stacked}}
A lightweight progress bar directive that is focused on providing progress visualization!
The progress bar directive supports multiple (stacked) bars into the same element, optional transition animation, event handler for full & empty state and many more.
<div ng-controller="ProgressDemoCtrl" class="well">
<h2>Static</h2>
<div class="row-fluid">
<div class="span4"><progress value="55"></progress></div>
<div class="span4"><progress value="22" class="progress-warning progress-striped"></progress></div>
<div class="span4"><progress value="88" class="progress-danger progress-striped active"></div>
</div>
<h2>Dynamic <button class="btn btn-primary" type="button" ng-click="random()">Randomize</button></h2>
<pre>Value: {{dynamic}}</pre>
<progress value="dynamic"></progress>
<small><em>No animation</em></small>
<progress value="dynamic" class="progress-success" animate="false"></progress>
<small><em>Object (changes type based on value)</em></small>
<progress value="dynamicObject" class="progress-striped active"></progress>
<h2>Stacked <button class="btn btn-primary" type="button" ng-click="randomStacked()">Randomize</button></h2>
<small><em>Array values with automatic types</em></small>
<pre>Value: {{stackedArray}}</pre>
<progress value="stackedArray" auto-type="true"></progress>
<small><em>Objects</em></small>
<pre>Value: {{stacked}}</pre>
<progress value="stacked"></progress>
</div>
var ProgressDemoCtrl = function ($scope) {
$scope.random = function() {
var value = Math.floor((Math.random()*100)+1);
var type;
if (value < 25) {
type = 'success';
} else if (value < 50) {
type = 'info';
} else if (value < 75) {
type = 'warning';
} else {
type = 'danger';
}
$scope.dynamic = value;
$scope.dynamicObject = {
value: value,
type: type
};
};
$scope.random();
var types = ['success', 'info', 'warning', 'danger'];
$scope.randomStacked = function() {
$scope.stackedArray = [];
$scope.stacked = [];
var n = Math.floor((Math.random()*4)+1);
for (var i=0; i < n; i++) {
var value = Math.floor((Math.random()*30)+1);
$scope.stackedArray.push(value);
var index = Math.floor((Math.random()*4));
$scope.stacked.push({
value: value,
type: types[index]
});
}
};
$scope.randomStacked();
};
Rating (ui.bootstrap.rating)
Rate: {{rate}} - Readonly is: {{isReadonly}}
Rating directive that will take care of visualising a star rating bar.
It also provides optional attribute max
to vary the number of stars and readonly
attribute to diasble user's interaction.
<div ng-controller="RatingDemoCtrl">
<rating value="rate" max="10" readonly="isReadonly"></rating>
<hr/>
<pre>Rate: <b>{{rate}}</b> - Readonly is: <i>{{isReadonly}}</i></pre>
<hr/>
<button class="btn btn-small btn-danger" ng-click="rate = 0" ng-disabled="isReadonly">Clear</button>
<button class="btn btn-small" ng-click="isReadonly = ! isReadonly">Toggle Readonly</button>
</div>
var RatingDemoCtrl = function ($scope) {
$scope.rate = 7;
$scope.isReadonly = false;
};
Tabs (ui.bootstrap.tabs)
AngularJS version of the tabs directive.
<div ng-controller="TabsDemoCtrl">
<tabs>
<pane heading="Static title">Static content</pane>
<pane ng-repeat="pane in panes" heading="{{pane.title}}" active="pane.active">{{pane.content}}</pane>
</tabs>
<div class="row-fluid">
<button class="btn" ng-click="panes[0].active = true">Select second tab</button>
<button class="btn" ng-click="panes[1].active = true">Select third tab</button>
</div>
</div>
var TabsDemoCtrl = function ($scope) {
$scope.panes = [
{ title:"Dynamic Title 1", content:"Dynamic content 1" },
{ title:"Dynamic Title 2", content:"Dynamic content 2" }
];
};
Typeahead (ui.bootstrap.typeahead)
Model: {{selected| json}}
Typeahead is a AngularJS version of Twitter Bootstrap typeahead plugin
This directive can be used to quickly create elegant typeheads with any form text input.
It is very well integrated into the AngularJS as:
- it uses the same, flexible syntax as the select directive
- works with promises and it means that you can retrieve matches using the
$http
service with minimal effort
<div class='container-fluid' ng-controller="TypeaheadCtrl">
<pre>Model: {{selected| json}}</pre>
<input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue">
</div>
function TypeaheadCtrl($scope) {
$scope.selected = undefined;
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
}