Getting started
Dependencies
This repository contains a set of native AngularJS directives based on Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's JavaScript is required. The only required dependencies are:
- AngularJS (requires AngularJS 1.3.x, tested with 1.4.7). 0.12.0 is the last version of this library that supports AngularJS 1.2.x.
- Bootstrap CSS (tested with version 3.1.1). This version of the library (0.14.1) works only with Bootstrap CSS in version 3.x. 0.8.0 is the last version of this library that supports Bootstrap CSS in version 2.3.x.
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. It should be noted that the -tpls
files contain the templates bundled in JavaScript, while the regular version does not contain the bundled templates. For more information, check out the FAQ here and the README 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: <76kB for all directives (~20kB 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.
Migration to prefixes
Since version 0.14.0 we started to prefix all our components. If you are upgrading from ui-bootstrap 0.13.4 or earlier, check our migration guide.
CSS
Original Bootstrap's CSS depends on empty href
attributes to style cursors for several components (pagination, tabs etc.).
But in AngularJS adding empty href
attributes to link tags will cause unwanted route changes. This is why we need to remove empty href
attributes from directive templates and as a result styling is not applied correctly. The remedy is simple, just add the following styling to your application:
.nav, .pagination, .carousel, .panel-title a { cursor: pointer; }
FAQ
Please check our FAQ section for common problems / solutions.
Reading the documentation
Each of the directives provided in ui-bootstrap
have documentation and interactive Plunker examples. There is also a list of settings which outline the default
values of settings, and whether they are readonly. In addition to this, some settings have an eye icon next to them like this . The
eye means that the setting has an Angular $watch listener applied to it.
Accordion (ui.bootstrap.accordion)
The body of the uib-accordion group grows to fit the contents
Please, to delete your account, click the button below
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.
The body of each accordion group is transcluded into the body of the collapsible element.
uib-accordion Settings
close-others
(Default:false
) - Control whether expanding an item will cause the other items to close.template-url
(Default:template/accordion/accordion.html
) - Add the ability to override the template used on the component.
uib-accordion Group Settings
is-disabled
(Default:false
) - Whether the accordion group is disabled or not.is-open
(Default:false
) - Whether accordion group is open or closed.heading
(Default:none
) - The clickable text on the group's header. You need one to be able to click on the header for toggling.panel-class
(Default:panel-default
) - Add ability to use Bootstrap's contextual panel classes (panel-primary, panel-success, panel-info, etc...) or your own. This must be a string.template-url
(Default:template/accordion/accordion-group.html
) - Add the ability to override the template used on the component.
Accordion heading
Instead of the heading
attribute on the uib-accordion-group
, you can use an uib-accordion-heading
element inside a group that will be used as the group's header.
<div ng-controller="AccordionDemoCtrl">
<script type="text/ng-template" id="group-template.html">
<div class="panel {{panelClass || 'panel-default'}}">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span
ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</div>
</script>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="status.open = !status.open">Toggle last panel</button>
<button type="button" class="btn btn-default btn-sm" ng-click="status.isFirstDisabled = ! status.isFirstDisabled">Enable / Disable first panel</button>
</p>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
</div>
<uib-accordion close-others="oneAtATime">
<uib-accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</uib-accordion-group>
<uib-accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</uib-accordion-group>
<uib-accordion-group heading="Dynamic Body Content">
<p>The body of the uib-accordion group grows to fit the contents</p>
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</uib-accordion-group>
<uib-accordion-group heading="Custom template" template-url="group-template.html">
Hello
</uib-accordion-group>
<uib-accordion-group heading="Delete account" panel-class="panel-danger">
<p>Please, to delete your account, click the button below</p>
<button class="btn btn-danger">Delete</button>
</uib-accordion-group>
<uib-accordion-group is-open="status.open">
<uib-accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</uib-accordion-heading>
This is just some content to illustrate fancy headings.
</uib-accordion-group>
</uib-accordion>
</div>
angular.module('ui.bootstrap.demo').controller('AccordionDemoCtrl', function ($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);
};
$scope.status = {
isFirstOpen: true,
isFirstDisabled: false
};
});
Alert (ui.bootstrap.alert)
This directive can be used both to generate alerts from static and dynamic model data (using the ng-repeat
directive).
uib-alert settings
close
(Default:none
) - A callback function that gets fired when analert
is closed. If the attribute exists, a close button is displayed as well.dismiss-on-timeout
(Default:none
)(Optional) - Takes the number of milliseconds that specify the timeout duration, after which the alert will be closed. This attribute requires the presence of theclose
attribute.template-url
(Default:template/alert/alert.html
) - Add the ability to override the template used in the component.type
(Default:warning
) - Defines the type of the alert. Go to bootstrap page to see the type of alerts available.
<div ng-controller="AlertDemoCtrl">
<script type="text/ng-template" id="alert.html">
<div class="alert" style="background-color:#fa39c3;color:white" role="alert">
<div ng-transclude></div>
</div>
</script>
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
<uib-alert template-url="alert.html">A happy alert!</uib-alert>
<button type="button" class='btn btn-default' ng-click="addAlert()">Add Alert</button>
</div>
angular.module('ui.bootstrap.demo').controller('AlertDemoCtrl', function ($scope) {
$scope.alerts = [
{ type: 'danger', 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)
Enter a negative number or 0 to stop the interval.
Carousel creates a carousel similar to bootstrap's image carousel.
The carousel also offers support for touchscreen devices in the form of swiping. To enable swiping, load the ngTouch
module as a dependency.
Use a <uib-carousel>
element with <uib-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.
Use the no-wrap
attribute on a <uib-carousel>
element to control the looping of slides; setting no-wrap
to an expression which evaluates to a truthy value will prevent looping.
Use the template-url
attribute on a <uib-carousel>
or <uib-slide>
element to specify the url of a custom template to override the default templates.
Use the actual
attribute on a <uib-slide>
element to bind the slide model (or any object of interest) onto the slide directive's $scope
, which makes it available for customization in the carousel template.
<div ng-controller="CarouselDemoCtrl">
<div style="height: 305px">
<uib-carousel interval="myInterval" no-wrap="noWrapSlides">
<uib-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>
</uib-slide>
</uib-carousel>
</div>
<div class="row">
<div class="col-md-6">
<button type="button" class="btn btn-info" ng-click="addSlide()">Add Slide</button>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="noWrapSlides">
Disable Slide Looping
</label>
</div>
</div>
<div class="col-md-6">
Interval, in milliseconds: <input type="number" class="form-control" ng-model="myInterval">
<br />Enter a negative number or 0 to stop the interval.
</div>
</div>
</div>
angular.module('ui.bootstrap.demo').controller('CarouselDemoCtrl', function ($scope) {
$scope.myInterval = 5000;
$scope.noWrapSlides = false;
var slides = $scope.slides = [];
$scope.addSlide = function() {
var newWidth = 600 + slides.length + 1;
slides.push({
image: '//placekitten.com/' + newWidth + '/300',
text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' ' +
['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4]
});
};
for (var i=0; i<4; i++) {
$scope.addSlide();
}
});
Collapse (ui.bootstrap.collapse)
uib-collapse provides a simple way to hide and show an element with a css transition
uib-collapse settings
uib-collapse
(Default:false
) - Whether the element should be collapsed or not.
<div ng-controller="CollapseDemoCtrl">
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
<hr>
<div uib-collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
angular.module('ui.bootstrap.demo').controller('CollapseDemoCtrl', function ($scope) {
$scope.isCollapsed = false;
});
Datepicker (ui.bootstrap.datepicker)
Selected date is: {{dt | date:'fullDate' }}
Inline
Popup
A clean, flexible, and fully customizable date picker.
User can navigate through months and years. The datepicker shows dates that come from other than the main month being displayed. These other dates are also selectable.
Everything is formatted using the date filter and thus is also localized.
Datepicker Settings
All settings can be provided as attributes in the uib-datepicker
or globally configured through the uibDatepickerConfig
.
ng-model
: The date object. Needs to be a Javascript Date object.datepicker-mode
(Defaults: 'day') : Current mode of the datepicker (day|month|year). Can be used to initialize datepicker to specific mode.min-date
(Default: null) : Defines the minimum available date.max-date
(Default: null) : Defines the maximum available date.date-disabled (date, mode)
(Default: null) : An optional expression to disable visible options based on passing date and current mode (day|month|year).custom-class (date, mode)
(Default: null) : An optional expression to add classes based on passing date and current mode (day|month|year).show-weeks
(Defaults: true) : Whether to display week numbers.starting-day
(Defaults: 0) : Starting day of the week from 0-6 (0=Sunday, ..., 6=Saturday).init-date
: The initial date view when no model value is specified.min-mode
(Defaults: 'day') : Set a lower limit for mode.max-mode
(Defaults: 'year') : Set an upper limit for mode.format-day
(Default: 'dd') : Format of day in month.format-month
(Default: 'MMMM') : Format of month in year.format-year
(Default: 'yyyy') : Format of year in year range.format-day-header
(Default: 'EEE') : Format of day in week header.format-day-title
(Default: 'MMMM yyyy') : Format of title when selecting day.format-month-title
(Default: 'yyyy') : Format of title when selecting month.year-range
(Default: 20) : Number of years displayed in year selection.shortcut-propagation
(Default: false) : An option to disable or enable shortcut's event propagation.template-url
(Default: 'template/datepicker/datepicker.html') : Allows overriding of default template of the datepicker
Popup Settings
Options for datepicker can be passed as JSON using the datepicker-options
attribute.
Specific settings for the uib-datepicker-popup
, that can globally configured through the uibDatepickerPopupConfig
, are:
uib-datepicker-popup
(Default: 'yyyy-MM-dd') : The format for displayed dates.show-button-bar
(Default: true) : Whether to display a button bar underneath the datepicker.current-text
(Default: 'Today') : The text to display for the current day button.clear-text
(Default: 'Clear') : The text to display for the clear button.close-text
(Default: 'Done') : The text to display for the close button.close-on-date-selection
(Default: true) : Whether to close calendar when a date is chosen.datepicker-popup-template-url
(Default: 'template/datepicker/popup.html') : Allows overriding of default template of the popupdatepicker-template-url
(Default: 'template/datepicker/datepicker.html') : Allows overriding of default template of the datepicker used in popupdatepicker-append-to-body
(Default: false): Append the datepicker popup element tobody
, rather than inserting afterdatepicker-popup
. For global configuration, useuibDatepickerPopupConfig.appendToBody
.is-open
(Default: false): Whether to show the datepicker.on-open-focus
(Default: true): Whether to focus the datepicker popup upon opening.
Keyboard Support
Depending on datepicker's current mode, the date may refer either to day, month or year. Accordingly, the term view refers either to a month, year or year range.
Left
: Move focus to the previous date. Will move to the last date of the previous view, if the current date is the first date of a view.Right
: Move focus to the next date. Will move to the first date of the following view, if the current date is the last date of a view.Up
: Move focus to the same column of the previous row. Will wrap to the appropriate row in the previous view.Down
: Move focus to the same column of the following row. Will wrap to the appropriate row in the following view.PgUp
: Move focus to the same date of the previous view. If that date does not exist, focus is placed on the last date of the month.PgDn
: Move focus to the same date of the following view. If that date does not exist, focus is placed on the last date of the month.Home
: Move to the first date of the view.End
: Move to the last date of the view.Enter
/Space
: Select date.Ctrl
+Up
: Move to an upper mode.Ctrl
+Down
: Move to a lower mode.Esc
: Will close popup, and move focus to the input.
<style>
.full button span {
background-color: limegreen;
border-radius: 32px;
color: black;
}
.partially button span {
background-color: orange;
border-radius: 32px;
color: black;
}
</style>
<div ng-controller="DatepickerDemoCtrl">
<pre>Selected date is: <em>{{dt | date:'fullDate' }}</em></pre>
<h4>Inline</h4>
<div style="display:inline-block; min-height:290px;">
<uib-datepicker ng-model="dt" min-date="minDate" show-weeks="true" class="well well-sm" custom-class="getDayClass(date, mode)"></uib-datepicker>
</div>
<h4>Popup</h4>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="status.opened" min-date="minDate" max-date="maxDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<div class="col-md-6">
<p class="input-group">
<input type="date" class="form-control" uib-datepicker-popup ng-model="dt" is-open="status.opened" min-date="minDate" max-date="maxDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Format:</label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
</div>
</div>
<hr />
<button type="button" class="btn btn-sm btn-info" ng-click="today()">Today</button>
<button type="button" class="btn btn-sm btn-default" ng-click="setDate(2009, 7, 24)">2009-08-24</button>
<button type="button" class="btn btn-sm btn-danger" ng-click="clear()">Clear</button>
<button type="button" class="btn btn-sm btn-default" ng-click="toggleMin()" uib-tooltip="After today restriction">Min date</button>
</div>
angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function () {
$scope.dt = null;
};
// Disable weekend selection
$scope.disabled = function(date, mode) {
return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.maxDate = new Date(2020, 5, 22);
$scope.open = function($event) {
$scope.status.opened = true;
};
$scope.setDate = function(year, month, day) {
$scope.dt = new Date(year, month, day);
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
$scope.status = {
opened: false
};
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var afterTomorrow = new Date();
afterTomorrow.setDate(tomorrow.getDate() + 2);
$scope.events =
[
{
date: tomorrow,
status: 'full'
},
{
date: afterTomorrow,
status: 'partially'
}
];
$scope.getDayClass = function(date, mode) {
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0,0,0,0);
for (var i=0;i<$scope.events.length;i++){
var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0);
if (dayToCheck === currentDay) {
return $scope.events[i].status;
}
}
}
return '';
};
});
Dropdown (ui.bootstrap.dropdown)
Dropdown is a simple directive which will toggle a dropdown menu on click or programmatically.
You can either use is-open
to toggle or add inside a <a uib-dropdown-toggle>
element to toggle it when is clicked.
There is also the on-toggle(open)
optional expression fired when dropdown changes state.
Add dropdown-append-to-body
to the uib-dropdown
element to append to the inner dropdown-menu
to the body.
This is useful when the dropdown button is inside a div with overflow: hidden
, and the menu would otherwise be hidden.
Add uib-keyboard-nav
to the uib-dropdown
element to enable navigation of dropdown list elements with the arrow keys.
By default the dropdown will automatically close if any of its elements is clicked, you can change this behavior by setting the auto-close
option as follows:
always
- (Default) automatically closes the dropdown when any of its elements is clicked.outsideClick
- closes the dropdown automatically only when the user clicks any element outside the dropdown.disabled
- disables the auto close. You can then control the open/close status of the dropdown manually, by usingis-open
. Please notice that the dropdown will still close if the toggle is clicked, theesc
key is pressed or another dropdown is open. The dropdown will no longer close on$locationChangeSuccess
events.
Optionally, you may specify a template for the dropdown menu using the template-url
attribute. This is especially useful when you have multiple similar dropdowns in a repeater and you want to keep your HTML output lean and your number of scopes to a minimum. The template has full access to the scope in which the dropdown lies.
Example: <ul class="uib-dropdown-menu" template-url="custom-dropdown.html"></ul>
.
<div ng-controller="DropdownCtrl">
<!-- Simple dropdown -->
<span uib-dropdown on-toggle="toggled(open)">
<a href id="simple-dropdown" uib-dropdown-toggle>
Click me for a dropdown, yo!
</a>
<ul class="uib-dropdown-menu" aria-labelledby="simple-dropdown">
<li ng-repeat="choice in items">
<a href>{{choice}}</a>
</li>
</ul>
</span>
<!-- Single button -->
<div class="btn-group" uib-dropdown is-open="status.isopen">
<button id="single-button" type="button" class="btn btn-primary" uib-dropdown-toggle ng-disabled="disabled">
Button dropdown <span class="caret"></span>
</button>
<ul class="uib-dropdown-menu" role="menu" aria-labelledby="single-button">
<li role="menuitem"><a href="#">Action</a></li>
<li role="menuitem"><a href="#">Another action</a></li>
<li role="menuitem"><a href="#">Something else here</a></li>
<li class="divider"></li>
<li role="menuitem"><a href="#">Separated link</a></li>
</ul>
</div>
<!-- Split button -->
<div class="btn-group" uib-dropdown>
<button id="split-button" type="button" class="btn btn-danger">Action</button>
<button type="button" class="btn btn-danger" uib-dropdown-toggle>
<span class="caret"></span>
<span class="sr-only">Split button!</span>
</button>
<ul class="uib-dropdown-menu" role="menu" aria-labelledby="split-button">
<li role="menuitem"><a href="#">Action</a></li>
<li role="menuitem"><a href="#">Another action</a></li>
<li role="menuitem"><a href="#">Something else here</a></li>
<li class="divider"></li>
<li role="menuitem"><a href="#">Separated link</a></li>
</ul>
</div>
<!-- Single button using append-to-body -->
<div class="btn-group" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button" class="btn btn-primary" uib-dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="uib-dropdown-menu" role="menu" aria-labelledby="btn-append-to-body">
<li role="menuitem"><a href="#">Action</a></li>
<li role="menuitem"><a href="#">Another action</a></li>
<li role="menuitem"><a href="#">Something else here</a></li>
<li class="divider"></li>
<li role="menuitem"><a href="#">Separated link</a></li>
</ul>
</div>
<!-- Single button using template-url -->
<div class="btn-group" uib-dropdown>
<button id="button-template-url" type="button" class="btn btn-primary" uib-dropdown-toggle ng-disabled="disabled">
Dropdown using template <span class="caret"></span>
</button>
<ul class="uib-dropdown-menu" template-url="dropdown.html" aria-labelledby="button-template-url">
</ul>
</div>
<hr />
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="toggleDropdown($event)">Toggle button dropdown</button>
<button type="button" class="btn btn-warning btn-sm" ng-click="disabled = !disabled">Enable/Disable</button>
</p>
<hr>
<!-- Single button with keyboard nav -->
<div class="btn-group" uib-dropdown uib-keyboard-nav>
<button id="simple-btn-keyboard-nav" type="button" class="btn btn-primary" uib-dropdown-toggle>
Dropdown with keyboard navigation <span class="caret"></span>
</button>
<ul class="uib-dropdown-menu" role="menu" aria-labelledby="simple-btn-keyboard-nav">
<li role="menuitem"><a href="#">Action</a></li>
<li role="menuitem"><a href="#">Another action</a></li>
<li role="menuitem"><a href="#">Something else here</a></li>
<li class="divider"></li>
<li role="menuitem"><a href="#">Separated link</a></li>
</ul>
</div>
<script type="text/ng-template" id="dropdown.html">
<ul class="uib-dropdown-menu" role="menu" aria-labelledby="button-template-url">
<li role="menuitem"><a href="#">Action in Template</a></li>
<li role="menuitem"><a href="#">Another action in Template</a></li>
<li role="menuitem"><a href="#">Something else here</a></li>
<li class="divider"></li>
<li role="menuitem"><a href="#">Separated link in Template</a></li>
</ul>
</script>
</div>
angular.module('ui.bootstrap.demo').controller('DropdownCtrl', function ($scope, $log) {
$scope.items = [
'The first choice!',
'And another choice for you.',
'but wait! A third!'
];
$scope.status = {
isopen: false
};
$scope.toggled = function(open) {
$log.log('Dropdown is now: ', open);
};
$scope.toggleDropdown = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.status.isopen = !$scope.status.isopen;
};
});
Modal (ui.bootstrap.modal)
$uibModal
is a service to quickly create AngularJS-powered modal windows.
Creating custom modals is straightforward: create a partial view, its controller and reference them when using the service.
The $uibModal
service has only one method: open(options)
where available options are like follows:
templateUrl
- a path to a template representing modal's contenttemplate
- inline template representing the modal's contentscope
- a scope instance to be used for the modal's content (actually the$uibModal
service is going to create a child scope of a provided scope). Defaults to$rootScope
controller
- a controller for a modal instance - it can initialize scope used by modal. Accepts the "controller-as" syntax in the form 'SomeCtrl as myctrl'; can be injected with$modalInstance
controllerAs
- an alternative to the controller-as syntax, matching the API of directive definitions. Requires thecontroller
option to be provided as wellbindToController
- when used withcontrollerAs
& set totrue
, it will bind the $scope properties onto the controller directlyresolve
- members that will be resolved and passed to the controller as locals; it is equivalent of theresolve
property for AngularJS routesanimation
- set to false to disable animations on new modal/backdrop. Does not toggle animations for modals/backdrops that are already displayed.backdrop
- controls presence of a backdrop. Allowed values: true (default), false (no backdrop),'static'
- backdrop is present but modal window is not closed when clicking outside of the modal window.keyboard
- indicates whether the dialog should be closable by hitting the ESC key, defaults to truebackdropClass
- additional CSS class(es) to be added to a modal backdrop templatewindowClass
- additional CSS class(es) to be added to a modal window templatewindowTopClass
- CSS class(es) to be added to the top modal windowwindowTemplateUrl
- a path to a template overriding modal's window templatesize
- optional suffix of modal window class. The value used is appended to themodal-
class, i.e. a value ofsm
givesmodal-sm
openedClass
- class added to thebody
element when the modal is opened. Defaults tomodal-open
Global defaults may be set for $uibModal
via $uibModalProvider.options
.
The open
method returns a modal instance, an object with the following properties:
close(result)
- a method that can be used to close a modal, passing a resultdismiss(reason)
- a method that can be used to dismiss a modal, passing a reasonresult
- a promise that is resolved when a modal is closed and rejected when a modal is dismissedopened
- a promise that is resolved when a modal gets opened after downloading content's template and resolving all variablesrendered
- a promise that is resolved when a modal is rendered.
In addition the scope associated with modal's content is augmented with 2 methods:
$close(result)
$dismiss(reason)
Those methods make it easy to close a modal window without a need to create a dedicated controller.
If the $scope is destroyed via unexpected mechanism, such as it being passed in the modal options and a $route/$state transition occurs, the modal will be dismissed with the value $uibUnscheduledDestruction
.
Finally, a modal.closing
event is broadcast to the modal scope before the modal closes. If the listener calls
preventDefault on the event, then the modal will remain open. The $close and $dismiss methods return true if the
event was allowed. The event itself includes a parameter for the result/reason and a boolean parameter that indicates
whether the modal is being closed (true) or dismissed.
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">
<a href="#" ng-click="$event.preventDefault(); selected.item = item">{{ item }}</a>
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
<button type="button" class="btn btn-default" ng-click="open()">Open me!</button>
<button type="button" class="btn btn-default" ng-click="open('lg')">Large modal</button>
<button type="button" class="btn btn-default" ng-click="open('sm')">Small modal</button>
<button type="button" class="btn btn-default" ng-click="toggleAnimation()">Toggle Animation ({{ animationsEnabled }})</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
Pagination (ui.bootstrap.pagination)
Default
The selected page no: {{currentPage}}
Pager
Limit the maximum visible buttons
Page: {{bigCurrentPage}} / {{numPages}}
A lightweight pagination directive that is focused on ... providing pagination & will take care of visualising a pagination bar and enable / disable buttons correctly!
Pagination Settings
Settings can be provided as attributes in the <uib-pagination>
or globally configured through the uibPaginationConfig
.
ng-change
:ng-change
can be used together withng-model
to call a function whenever the page changes.ng-model
: Current page number. First page is 1.ng-disabled
: Used to disable the pagination componenttotal-items
: Total number of items in all pages.items-per-page
(Defaults: 10) : Maximum number of items per page. A value less than one indicates all items on one page.max-size
(Defaults: null) : Limit number for pagination size.num-pages
readonly (Defaults: angular.noop) : An optional expression assigned the total number of pages to display.rotate
(Defaults: true) : Whether to keep current page in the middle of the visible ones.direction-links
(Default: true) : Whether to display Previous / Next buttons.previous-text
(Default: 'Previous') : Text for Previous button.next-text
(Default: 'Next') : Text for Next button.boundary-links
(Default: false) : Whether to display First / Last buttons.first-text
(Default: 'First') : Text for First button.last-text
(Default: 'Last') : Text for Last button.template-url
(Default: 'template/pagination/pagination.html') : Override the template for the component with a custom provided template
Pager Settings
Settings can be provided as attributes in the <uib-pager>
or globally configured through the uibPagerConfig
.
For ng-model
, total-items
, items-per-page
and num-pages
see pagination settings. Other settings are:
align
(Default: true) : Whether to align each link to the sides.previous-text
(Default: '« Previous') : Text for Previous button.next-text
(Default: 'Next »') : Text for Next button.template-url
_(Default: 'template/pagination/pager.html') : Override the template for the component with a custom provided templateng-disabled
: Used to disable the pager component
<div ng-controller="PaginationDemoCtrl">
<h4>Default</h4>
<uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination>
<uib-pagination boundary-links="true" total-items="totalItems" ng-model="currentPage" class="pagination-sm" previous-text="‹" next-text="›" first-text="«" last-text="»"></uib-pagination>
<uib-pagination direction-links="false" boundary-links="true" total-items="totalItems" ng-model="currentPage"></uib-pagination>
<uib-pagination direction-links="false" total-items="totalItems" ng-model="currentPage" num-pages="smallnumPages"></uib-pagination>
<pre>The selected page no: {{currentPage}}</pre>
<button type="button" class="btn btn-info" ng-click="setPage(3)">Set current page to: 3</button>
<hr />
<h4>Pager</h4>
<uib-pager total-items="totalItems" ng-model="currentPage"></uib-pager>
<hr />
<h4>Limit the maximum visible buttons</h4>
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true"></uib-pagination>
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" rotate="false" num-pages="numPages"></uib-pagination>
<pre>Page: {{bigCurrentPage}} / {{numPages}}</pre>
</div>
angular.module('ui.bootstrap.demo').controller('PaginationDemoCtrl', function ($scope, $log) {
$scope.totalItems = 64;
$scope.currentPage = 4;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.pageChanged = function() {
$log.log('Page changed to: ' + $scope.currentPage);
};
$scope.maxSize = 5;
$scope.bigTotalItems = 175;
$scope.bigCurrentPage = 1;
});
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 Bootstrap jQuery plugin, the popover requires the tooltip module.
There are two versions of the popover: uib-popover
and uib-popover-template
:
uib-popover
takes text only and will escape any HTML provided for the popover body.uib-popover-html
takes an expression that evaluates to an html string. The user is responsible for ensuring the content is safe to put into the DOM!uib-popover-template
takes text that specifies the location of a template to use for the popover body. Note that this needs to be wrapped in a tag.
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", "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.popover-append-to-body
: Should the tooltip be appended to$body
instead of the parent element?popover-is-open
(Default: false): Whether to show the popover.
The popover directives require the $position
service.
The popover directive also supports various default configurations through the $tooltipProvider. See the tooltip section for more information.
Known issues
For Safari 7+ support, if you want to use focus popover-trigger
, you need to use an anchor tag with a tab index. For example:
<a tabindex="0" uib-popover="Test" popover-trigger="focus" class="btn btn-default">
Click Me
</a>
<div ng-controller="PopoverDemoCtrl">
<h4>Dynamic</h4>
<div class="form-group">
<label>Popup Text:</label>
<input type="text" ng-model="dynamicPopover.content" class="form-control">
</div>
<div class="form-group">
<label>Popup Title:</label>
<input type="text" ng-model="dynamicPopover.title" class="form-control">
</div>
<div class="form-group">
<label>Popup Template:</label>
<input type="text" ng-model="dynamicPopover.templateUrl" class="form-control">
</div>
<button uib-popover="{{dynamicPopover.content}}" popover-title="{{dynamicPopover.title}}" type="button" class="btn btn-default">Dynamic Popover</button>
<button uib-popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" type="button" class="btn btn-default">Popover With Template</button>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>{{dynamicPopover.content}}</div>
<div class="form-group">
<label>Popup Title:</label>
<input type="text" ng-model="dynamicPopover.title" class="form-control">
</div>
</script>
<hr />
<h4>Positional</h4>
<button popover-placement="top" uib-popover="On the Top!" type="button" class="btn btn-default">Top</button>
<button popover-placement="left" uib-popover="On the Left!" type="button" class="btn btn-default">Left</button>
<button popover-placement="right" uib-popover="On the Right!" type="button" class="btn btn-default">Right</button>
<button popover-placement="bottom" uib-popover="On the Bottom!" type="button" class="btn btn-default">Bottom</button>
<hr />
<h4>Triggers</h4>
<p>
<button uib-popover="I appeared on mouse enter!" popover-trigger="mouseenter" type="button" class="btn btn-default">Mouseenter</button>
</p>
<input type="text" value="Click me!" uib-popover="I appeared on focus! Click away and I'll vanish..." popover-trigger="focus" class="form-control">
<hr />
<h4>Other</h4>
<button popover-animation="true" uib-popover="I fade in and out!" type="button" class="btn btn-default">fading</button>
<button uib-popover="I have a title!" popover-title="The title." type="button" class="btn btn-default">title</button>
</div>
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope) {
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
});
Progressbar (ui.bootstrap.progressbar)
Static
Dynamic
Stacked
A progress bar directive that is focused on providing feedback on the progress of a workflow or action.
It supports multiple (stacked) bars into the same <uib-progress>
element or a single <progressbar>
element with optional max
attribute and transition animations.
Settings
<uib-progressbar>
value
: The current value of progress completed.type
(Default: null) : Style type. Possible values are 'success', 'warning' etc.max
(Default: 100) : A number that specifies the total value of bars that is required.animate
(Default: true) : Whether bars use transitions to achieve the width change.title
(Default: progressbar) : Title to use as label (for accessibility)
Stacked
Place multiple <uib-bar>
s into the same <uib-progress>
element to stack them.
<uib-progress>
supports max
, animate
, and title
& <uib-bar>
supports value
, title
, and type
attributes.
<div ng-controller="ProgressDemoCtrl">
<h3>Static</h3>
<div class="row">
<div class="col-sm-4"><uib-progressbar value="55"></uib-progressbar></div>
<div class="col-sm-4"><uib-progressbar class="progress-striped" value="22" type="warning">22%</uib-progressbar></div>
<div class="col-sm-4"><uib-progressbar class="progress-striped active" max="200" value="166" type="danger"><i>166 / 200</i></uib-progressbar></div>
</div>
<hr />
<h3>Dynamic <button type="button" class="btn btn-sm btn-primary" ng-click="random()">Randomize</button></h3>
<uib-progressbar max="max" value="dynamic"><span style="color:white; white-space:nowrap;">{{dynamic}} / {{max}}</span></uib-progressbar>
<small><em>No animation</em></small>
<uib-progressbar animate="false" value="dynamic" type="success"><b>{{dynamic}}%</b></uib-progressbar>
<small><em>Object (changes type based on value)</em></small>
<uib-progressbar class="progress-striped active" value="dynamic" type="{{type}}">{{type}} <i ng-show="showWarning">!!! Watch out !!!</i></uib-progressbar>
<hr />
<h3>Stacked <button type="button" class="btn btn-sm btn-primary" ng-click="randomStacked()">Randomize</button></h3>
<uib-progress><uib-bar ng-repeat="bar in stacked track by $index" value="bar.value" type="{{bar.type}}"><span ng-hide="bar.value < 5">{{bar.value}}%</span></uib-bar></uib-progress>
</div>
angular.module('ui.bootstrap.demo').controller('ProgressDemoCtrl', function ($scope) {
$scope.max = 200;
$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.showWarning = (type === 'danger' || type === 'warning');
$scope.dynamic = value;
$scope.type = type;
};
$scope.random();
$scope.randomStacked = function() {
$scope.stacked = [];
var types = ['success', 'info', 'warning', 'danger'];
for (var i = 0, n = Math.floor((Math.random() * 4) + 1); i < n; i++) {
var index = Math.floor((Math.random() * 4));
$scope.stacked.push({
value: Math.floor((Math.random() * 30) + 1),
type: types[index]
});
}
};
$scope.randomStacked();
});
Rating (ui.bootstrap.rating)
Default
Rate: {{rate}} - Readonly is: {{isReadonly}} - Hovering over: {{overStar || "none"}}
Custom icons
Rating directive that will take care of visualising a star rating bar.
Settings
<uib-rating>
ng-model
: The current rate.max
(Defaults: 5) : Changes the number of icons.readonly
(Defaults: false) : Prevent user's interaction.titles
(Defaults: ["one", "two", "three", "four", "five"]) : An array of Strings defining titles for all iconson-hover(value)
: An optional expression called when user's mouse is over a particular icon.on-leave()
: An optional expression called when user's mouse leaves the control altogether.state-on
(Defaults: null) : A variable used in template to specify the state (class, src, etc) for selected icons.state-off
(Defaults: null) : A variable used in template to specify the state for unselected icons.rating-states
(Defaults: null) : An array of objects defining properties for all icons. In default template,stateOn
&stateOff
property is used to specify the icon's class.
<div ng-controller="RatingDemoCtrl">
<h4>Default</h4>
<uib-rating ng-model="rate" max="max" readonly="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null" titles="['one','two','three']" aria-labelledby="default-rating"></uib-rating>
<span class="label" ng-class="{'label-warning': percent<30, 'label-info': percent>=30 && percent<70, 'label-success': percent>=70}" ng-show="overStar && !isReadonly">{{percent}}%</span>
<pre style="margin:15px 0;">Rate: <b>{{rate}}</b> - Readonly is: <i>{{isReadonly}}</i> - Hovering over: <b>{{overStar || "none"}}</b></pre>
<button type="button" class="btn btn-sm btn-danger" ng-click="rate = 0" ng-disabled="isReadonly">Clear</button>
<button type="button" class="btn btn-sm btn-default" ng-click="isReadonly = ! isReadonly">Toggle Readonly</button>
<hr />
<h4>Custom icons</h4>
<div ng-init="x = 5"><uib-rating ng-model="x" max="15" state-on="'glyphicon-ok-sign'" state-off="'glyphicon-ok-circle'" aria-labelledby="custom-icons-1"></uib-rating> <b>(<i>Rate:</i> {{x}})</b></div>
<div ng-init="y = 2"><uib-rating ng-model="y" rating-states="ratingStates" aria-labelledby="custom-icons-2"></uib-rating> <b>(<i>Rate:</i> {{y}})</b></div>
</div>
angular.module('ui.bootstrap.demo').controller('RatingDemoCtrl', function ($scope) {
$scope.rate = 7;
$scope.max = 10;
$scope.isReadonly = false;
$scope.hoveringOver = function(value) {
$scope.overStar = value;
$scope.percent = 100 * (value / $scope.max);
};
$scope.ratingStates = [
{stateOn: 'glyphicon-ok-sign', stateOff: 'glyphicon-ok-circle'},
{stateOn: 'glyphicon-star', stateOff: 'glyphicon-star-empty'},
{stateOn: 'glyphicon-heart', stateOff: 'glyphicon-ban-circle'},
{stateOn: 'glyphicon-heart'},
{stateOff: 'glyphicon-off'}
];
});
Tabs (ui.bootstrap.tabs)
Select a tab by setting active binding to true:
AngularJS version of the tabs directive.
Settings
<uib-tabset>
vertical
(Defaults: false) : Whether tabs appear vertically stacked.justified
(Defaults: false) : Whether tabs fill the container and have a consistent width.type
(Defaults: 'tabs') : Navigation type. Possible values are 'tabs' and 'pills'.
<uib-tab>
heading
or<uib-tab-heading>
: Heading text or HTML markup.active
(Defaults: false) : Whether tab is currently selected.disable
(Defaults: false) : Whether tab is clickable and can be activated. Note that this was previously thedisabled
attribute, which is now deprecated.select()
(Defaults: null) : An optional expression called when tab is activated.deselect()
(Defaults: null) : An optional expression called when tab is deactivated.
<div ng-controller="TabsDemoCtrl">
<p>Select a tab by setting active binding to true:</p>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="tabs[0].active = true">Select second tab</button>
<button type="button" class="btn btn-default btn-sm" ng-click="tabs[1].active = true">Select third tab</button>
</p>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="tabs[1].disabled = ! tabs[1].disabled">Enable / Disable third tab</button>
</p>
<hr />
<uib-tabset>
<uib-tab heading="Static title">Static content</uib-tab>
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disable="tab.disabled">
{{tab.content}}
</uib-tab>
<uib-tab select="alertMe()">
<uib-tab-heading>
<i class="glyphicon glyphicon-bell"></i> Alert!
</uib-tab-heading>
I've got an HTML heading, and a select callback. Pretty cool!
</uib-tab>
</uib-tabset>
<hr />
<uib-tabset vertical="true" type="pills">
<uib-tab heading="Vertical 1">Vertical content 1</uib-tab>
<uib-tab heading="Vertical 2">Vertical content 2</uib-tab>
</uib-tabset>
<hr />
<uib-tabset justified="true">
<uib-tab heading="Justified">Justified content</uib-tab>
<uib-tab heading="SJ">Short Labeled Justified content</uib-tab>
<uib-tab heading="Long Justified">Long Labeled Justified content</uib-tab>
</uib-tabset>
</div>
angular.module('ui.bootstrap.demo').controller('TabsDemoCtrl', function ($scope, $window) {
$scope.tabs = [
{ title:'Dynamic Title 1', content:'Dynamic content 1' },
{ title:'Dynamic Title 2', content:'Dynamic content 2', disabled: true }
];
$scope.alertMe = function() {
setTimeout(function() {
$window.alert('You\'ve selected the alert tab!');
});
};
});
Timepicker (ui.bootstrap.timepicker)
Time is: {{mytime | date:'shortTime' }}
A lightweight & configurable timepicker directive.
Settings
All settings can be provided as attributes in the <uib-timepicker>
or globally configured through the uibTimepickerConfig
.
ng-model
: The Date object that provides the time state.template-url
(Defaults:template/timepicker/timepicker.html
) : Add the ability to override the template used on the component.
hour-step
(Defaults: 1) : Number of hours to increase or decrease when using a button.minute-step
(Defaults: 1) : Number of minutes to increase or decrease when using a button.show-meridian
(Defaults: true) : Whether to display 12H or 24H mode.meridians
(Defaults: null) : Meridian labels based on locale. To override you must supply an array like ['AM', 'PM'].readonly-input
(Defaults: false) : Whether user can type inside the hours & minutes input.mousewheel
(Defaults: true) : Whether user can scroll inside the hours & minutes input to increase or decrease it's values.arrowkeys
(Defaults: true) : Whether user can use up/down arrowkeys inside the hours & minutes input to increase or decrease it's values.show-spinners
(Defaults: true) : Shows spinner arrows above and below the inputsmin
(Defaults: undefined) : Minimum time a user can selectmax
(Defaults: undefined) : Maximum time a user can selecttabindex
(Defaults: 0) : Sets tabindex for each control in timepicker
<div ng-controller="TimepickerDemoCtrl">
<uib-timepicker ng-model="mytime" ng-change="changed()" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"></uib-timepicker>
<pre class="alert alert-info">Time is: {{mytime | date:'shortTime' }}</pre>
<div class="row">
<div class="col-xs-6">
Hours step is:
<select class="form-control" ng-model="hstep" ng-options="opt for opt in options.hstep"></select>
</div>
<div class="col-xs-6">
Minutes step is:
<select class="form-control" ng-model="mstep" ng-options="opt for opt in options.mstep"></select>
</div>
</div>
<hr>
<button type="button" class="btn btn-info" ng-click="toggleMode()">12H / 24H</button>
<button type="button" class="btn btn-default" ng-click="update()">Set to 14:00</button>
<button type="button" class="btn btn-danger" ng-click="clear()">Clear</button>
</div>
angular.module('ui.bootstrap.demo').controller('TimepickerDemoCtrl', function ($scope, $log) {
$scope.mytime = new Date();
$scope.hstep = 1;
$scope.mstep = 15;
$scope.options = {
hstep: [1, 2, 3],
mstep: [1, 5, 10, 15, 25, 30]
};
$scope.ismeridian = true;
$scope.toggleMode = function() {
$scope.ismeridian = ! $scope.ismeridian;
};
$scope.update = function() {
var d = new Date();
d.setHours( 14 );
d.setMinutes( 0 );
$scope.mytime = d;
};
$scope.changed = function () {
$log.log('Time changed to: ' + $scope.mytime);
};
$scope.clear = function() {
$scope.mytime = null;
};
});
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. Custom template nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
I can even contain HTML. Check me out!
I can have a custom class. Check me out!
A lightweight, extensible directive for fancy tooltip creation. The tooltip directive supports multiple placements, optional transition animation, and more.
There are three versions of the tooltip: uib-tooltip
, uib-tooltip-template
, and
uib-tooltip-html-unsafe
:
uib-tooltip
takes text only and will escape any HTML provided.uib-tooltip-template
takes text that specifies the location of a template to use for the tooltip. Note that this needs to be wrapped in a tag.uib-tooltip-html
takes whatever HTML is provided and displays it in a tooltip; The user is responsible for ensuring the content is safe to put into the DOM!uib-tooltip-html-unsafe
-- deprecated in favour oftooltip-html
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", "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-close-popup-delay
: For how long should the tooltip remained open?tooltip-trigger
: What should trigger a show of the tooltip? Supports a space separated list of event names. Note: this attribute is no longer observable. Seetooltip-enable
.tooltip-enable
: Is it enabled? It will enable or disable the configuredtooltip-trigger
.tooltip-append-to-body
: Should the tooltip be appended to$body
instead of the parent element?tooltip-class
: Custom class to be applied to the tooltip.tooltip-is-open
(Default: false): Whether to show 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
none
: ``
For any non-supported value, the trigger will be used to both show and hide the
tooltip. Using the 'none' trigger will disable the internal trigger(s), one can
then use the tooltip-is-open
attribute exclusively to show and hide the tooltip.
$uibTooltipProvider
Through the $uibTooltipProvider
, you can change the way tooltips and popovers
behave by default; the attributes above always take precedence. The following
methods are available:
setTriggers(obj)
: Extends the default trigger mappings mentioned above with mappings of your own. E.g.{ 'openTrigger': 'closeTrigger' }
.options(obj)
: Provide a set of defaults for certain tooltip and popover attributes. Currently supports 'placement', 'animation', 'popupDelay', andappendToBody
. Here are the defaults:placement: 'top', animation: true, popupDelay: 0, popupCloseDelay: 500, appendToBody: false
Known issues
For Safari 7+ support, if you want to use the focus tooltip-trigger
, you need to use an anchor tag with a tab index. For example:
<a tabindex="0" uib-tooltip="Test" tooltip-trigger="focus" class="btn btn-default">
Click Me
</a>
<div ng-controller="TooltipDemoCtrl">
<div class="form-group">
<label>Dynamic Tooltip Text</label>
<input type="text" ng-model="dynamicTooltipText" class="form-control">
</div>
<div class="form-group">
<label>Dynamic Tooltip Popup Text</label>
<input type="text" ng-model="dynamicTooltip" class="form-control">
</div>
<p>
Pellentesque <a href="#" uib-tooltip="{{dynamicTooltip}}">{{dynamicTooltipText}}</a>,
sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in
aliquam. Tincidunt lobortis feugiat vivamus at
<a href="#" tooltip-placement="left" uib-tooltip="On the Left!">left</a> eget
arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur
<a href="#" tooltip-placement="right" uib-tooltip="On the Right!">right</a>
nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
<a href="#" tooltip-placement="bottom" uib-tooltip="On the Bottom!">bottom</a>
pharetra convallis posuere morbi leo urna,
<a href="#" tooltip-animation="false" uib-tooltip="I don't fade. :-(">fading</a>
at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
<a href="#" tooltip-popup-delay='1000' uib-tooltip='appears with delay'>delayed</a> turpis massa tincidunt dui ut.
<a href="#" uib-tooltip-template="'myTooltipTemplate.html'">Custom template</a>
nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
</p>
<p>
I can even contain HTML. <a href="#" uib-tooltip-html="htmlTooltip">Check me out!</a>
</p>
<p>
<style>
/* Specify styling for tooltip contents */
.tooltip.customClass .tooltip-inner {
color: #880000;
background-color: #ffff66;
box-shadow: 0 6px 12px rgba(0,0,0,.175);
}
/* Hide arrow */
.tooltip.customClass .tooltip-arrow {
display: none;
}
</style>
I can have a custom class. <a href="#" uib-tooltip="I can have a custom class applied to me!" tooltip-class="customClass">Check me out!</a>
</p>
<form role="form">
<div class="form-group">
<label>Or use custom triggers, like focus: </label>
<input type="text" value="Click me!" uib-tooltip="See? Now click away..." tooltip-trigger="focus" tooltip-placement="right" class="form-control" />
</div>
<div class="form-group" ng-class="{'has-error' : !inputModel}">
<label>Disable tooltips conditionally:</label>
<input type="text" ng-model="inputModel" class="form-control"
placeholder="Hover over this for a tooltip until this is filled"
uib-tooltip="Enter something in this input field to disable this tooltip"
tooltip-placement="top"
tooltip-trigger="mouseenter"
tooltip-enable="!inputModel" />
</div>
</form>
<script type="text/ng-template" id="myTooltipTemplate.html">
<span>Special Tooltip with <strong>markup</strong> and {{ dynamicTooltipText }}</span>
</script>
</div>
angular.module('ui.bootstrap.demo').controller('TooltipDemoCtrl', function ($scope, $sce) {
$scope.dynamicTooltip = 'Hello, World!';
$scope.dynamicTooltipText = 'dynamic';
$scope.htmlTooltip = $sce.trustAsHtml('I\'ve been made <b>bold</b>!');
});
Typeahead (ui.bootstrap.typeahead)
Static arrays
Model: {{selected | json}}
Asynchronous results
Model: {{asyncSelected | json}}
Custom templates for results
Model: {{customSelected | json}}
Custom popup templates for typeahead's dropdown
Model: {{customPopupSelected | json}}
Typeahead is a AngularJS version of Bootstrap v2's typeahead plugin. This directive can be used to quickly create elegant typeaheads with any form text input.
It is very well integrated into AngularJS as it uses a subset of the select directive syntax, which is very flexible. Supported expressions are:
- label for value in sourceArray
- select as label for value in sourceArray
The sourceArray
expression can use a special $viewValue
variable that corresponds to the value entered inside the input.
This directive works with promises, meaning you can retrieve matches using the $http
service with minimal effort.
The typeahead directives provide several attributes:
ng-model
: Assignable angular expression to data-bind totypeahead
: Comprehension Angular expression (see select directive)typeahead-append-to-body
(Defaults: false) : Should the typeahead popup be appended to $body instead of the parent element?typeahead-append-to-element-id
(Defaults: false) : Should the typeahead popup be appended to an element id instead of the parent element?typeahead-editable
(Defaults: true) : Should it restrict model values to the ones selected from the popup only ?typeahead-focus-first
(Defaults: true) : Should the first match automatically be focused as you type?typeahead-input-formatter
(Defaults: undefined) : Format the ng-model result after selectiontypeahead-loading
(Defaults: angular.noop) : Binding to a variable that indicates if matches are being retrieved asynchronouslytypeahead-min-length
(Defaults: 1) : Minimal no of characters that needs to be entered before typeahead kicks-in. Must be greater than or equal to 1.typeahead-no-results
(Defaults: angular.noop) : Binding to a variable that indicates if no matching results were foundtypeahead-on-select($item, $model, $label)
(Defaults: null) : A callback executed when a match is selectedtypeahead-select-on-exact
(Defaults: false) : Should it automatically select an item when there is one option that exactly matches the user input?typeahead-template-url
: Set custom item templatetypeahead-popup-template-url
(Defaults:template/typeahead/typeahead-popup.html
) : Set custom popup templatetypeahead-wait-ms
(Defaults: 0) : Minimal wait time after last character typed before typeahead kicks-intypeahead-select-on-blur
(Defaults: false) : On blur, select the currently highlighted matchtypeahead-focus-on-select
_(Defaults: true) : On selection, focus the input element the typeahead directive is associated with
<style>
.typeahead-demo .custom-popup-wrapper {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
background-color: #f9f9f9;
}
.typeahead-demo .custom-popup-wrapper > .message {
padding: 10px 20px;
border-bottom: 1px solid #ddd;
color: #868686;
}
.typeahead-demo .custom-popup-wrapper > .dropdown-menu {
position: static;
float: none;
display: block;
min-width: 160px;
background-color: transparent;
border: none;
border-radius: 0;
box-shadow: none;
}
</style>
<script type="text/ng-template" id="customTemplate.html">
<a>
<img ng-src="http://upload.wikimedia.org/wikipedia/commons/thumb/{{match.model.flag}}" width="16">
<span ng-bind-html="match.label | uibTypeaheadHighlight:query"></span>
</a>
</script>
<script type="text/ng-template" id="customPopupTemplate.html">
<div class="custom-popup-wrapper"
ng-style="{top: position().top+'px', left: position().left+'px'}"
style="display: block;"
ng-show="isOpen() && !moveInProgress"
aria-hidden="{{!isOpen()}}">
<p class="message">select location from drop down.</p>
<ul class="dropdown-menu" role="listbox">
<li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }"
ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">
<div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>
</li>
</ul>
</div>
</script>
<div class='container-fluid typeahead-demo' ng-controller="TypeaheadCtrl">
<h4>Static arrays</h4>
<pre>Model: {{selected | json}}</pre>
<input type="text" ng-model="selected" uib-typeahead="state for state in states | filter:$viewValue | limitTo:8" class="form-control">
<h4>Asynchronous results</h4>
<pre>Model: {{asyncSelected | json}}</pre>
<input type="text" ng-model="asyncSelected" placeholder="Locations loaded via $http" uib-typeahead="address for address in getLocation($viewValue)" typeahead-loading="loadingLocations" typeahead-no-results="noResults" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
<div ng-show="noResults">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
<h4>Custom templates for results</h4>
<pre>Model: {{customSelected | json}}</pre>
<input type="text" ng-model="customSelected" placeholder="Custom template" uib-typeahead="state as state.name for state in statesWithFlags | filter:{name:$viewValue}" typeahead-template-url="customTemplate.html" class="form-control">
<h4>Custom popup templates for typeahead's dropdown</h4>
<pre>Model: {{customPopupSelected | json}}</pre>
<input type="text" ng-model="customPopupSelected" placeholder="Custom popup template" uib-typeahead="state as state.name for state in statesWithFlags | filter:{name:$viewValue}" typeahead-popup-template-url="customPopupTemplate.html" class="form-control">
</div>
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl', function($scope, $http) {
$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'];
// Any function returning a promise object can be used to load values asynchronously
$scope.getLocation = function(val) {
return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
return item.formatted_address;
});
});
};
$scope.statesWithFlags = [{'name':'Alabama','flag':'5/5c/Flag_of_Alabama.svg/45px-Flag_of_Alabama.svg.png'},{'name':'Alaska','flag':'e/e6/Flag_of_Alaska.svg/43px-Flag_of_Alaska.svg.png'},{'name':'Arizona','flag':'9/9d/Flag_of_Arizona.svg/45px-Flag_of_Arizona.svg.png'},{'name':'Arkansas','flag':'9/9d/Flag_of_Arkansas.svg/45px-Flag_of_Arkansas.svg.png'},{'name':'California','flag':'0/01/Flag_of_California.svg/45px-Flag_of_California.svg.png'},{'name':'Colorado','flag':'4/46/Flag_of_Colorado.svg/45px-Flag_of_Colorado.svg.png'},{'name':'Connecticut','flag':'9/96/Flag_of_Connecticut.svg/39px-Flag_of_Connecticut.svg.png'},{'name':'Delaware','flag':'c/c6/Flag_of_Delaware.svg/45px-Flag_of_Delaware.svg.png'},{'name':'Florida','flag':'f/f7/Flag_of_Florida.svg/45px-Flag_of_Florida.svg.png'},{'name':'Georgia','flag':'5/54/Flag_of_Georgia_%28U.S._state%29.svg/46px-Flag_of_Georgia_%28U.S._state%29.svg.png'},{'name':'Hawaii','flag':'e/ef/Flag_of_Hawaii.svg/46px-Flag_of_Hawaii.svg.png'},{'name':'Idaho','flag':'a/a4/Flag_of_Idaho.svg/38px-Flag_of_Idaho.svg.png'},{'name':'Illinois','flag':'0/01/Flag_of_Illinois.svg/46px-Flag_of_Illinois.svg.png'},{'name':'Indiana','flag':'a/ac/Flag_of_Indiana.svg/45px-Flag_of_Indiana.svg.png'},{'name':'Iowa','flag':'a/aa/Flag_of_Iowa.svg/44px-Flag_of_Iowa.svg.png'},{'name':'Kansas','flag':'d/da/Flag_of_Kansas.svg/46px-Flag_of_Kansas.svg.png'},{'name':'Kentucky','flag':'8/8d/Flag_of_Kentucky.svg/46px-Flag_of_Kentucky.svg.png'},{'name':'Louisiana','flag':'e/e0/Flag_of_Louisiana.svg/46px-Flag_of_Louisiana.svg.png'},{'name':'Maine','flag':'3/35/Flag_of_Maine.svg/45px-Flag_of_Maine.svg.png'},{'name':'Maryland','flag':'a/a0/Flag_of_Maryland.svg/45px-Flag_of_Maryland.svg.png'},{'name':'Massachusetts','flag':'f/f2/Flag_of_Massachusetts.svg/46px-Flag_of_Massachusetts.svg.png'},{'name':'Michigan','flag':'b/b5/Flag_of_Michigan.svg/45px-Flag_of_Michigan.svg.png'},{'name':'Minnesota','flag':'b/b9/Flag_of_Minnesota.svg/46px-Flag_of_Minnesota.svg.png'},{'name':'Mississippi','flag':'4/42/Flag_of_Mississippi.svg/45px-Flag_of_Mississippi.svg.png'},{'name':'Missouri','flag':'5/5a/Flag_of_Missouri.svg/46px-Flag_of_Missouri.svg.png'},{'name':'Montana','flag':'c/cb/Flag_of_Montana.svg/45px-Flag_of_Montana.svg.png'},{'name':'Nebraska','flag':'4/4d/Flag_of_Nebraska.svg/46px-Flag_of_Nebraska.svg.png'},{'name':'Nevada','flag':'f/f1/Flag_of_Nevada.svg/45px-Flag_of_Nevada.svg.png'},{'name':'New Hampshire','flag':'2/28/Flag_of_New_Hampshire.svg/45px-Flag_of_New_Hampshire.svg.png'},{'name':'New Jersey','flag':'9/92/Flag_of_New_Jersey.svg/45px-Flag_of_New_Jersey.svg.png'},{'name':'New Mexico','flag':'c/c3/Flag_of_New_Mexico.svg/45px-Flag_of_New_Mexico.svg.png'},{'name':'New York','flag':'1/1a/Flag_of_New_York.svg/46px-Flag_of_New_York.svg.png'},{'name':'North Carolina','flag':'b/bb/Flag_of_North_Carolina.svg/45px-Flag_of_North_Carolina.svg.png'},{'name':'North Dakota','flag':'e/ee/Flag_of_North_Dakota.svg/38px-Flag_of_North_Dakota.svg.png'},{'name':'Ohio','flag':'4/4c/Flag_of_Ohio.svg/46px-Flag_of_Ohio.svg.png'},{'name':'Oklahoma','flag':'6/6e/Flag_of_Oklahoma.svg/45px-Flag_of_Oklahoma.svg.png'},{'name':'Oregon','flag':'b/b9/Flag_of_Oregon.svg/46px-Flag_of_Oregon.svg.png'},{'name':'Pennsylvania','flag':'f/f7/Flag_of_Pennsylvania.svg/45px-Flag_of_Pennsylvania.svg.png'},{'name':'Rhode Island','flag':'f/f3/Flag_of_Rhode_Island.svg/32px-Flag_of_Rhode_Island.svg.png'},{'name':'South Carolina','flag':'6/69/Flag_of_South_Carolina.svg/45px-Flag_of_South_Carolina.svg.png'},{'name':'South Dakota','flag':'1/1a/Flag_of_South_Dakota.svg/46px-Flag_of_South_Dakota.svg.png'},{'name':'Tennessee','flag':'9/9e/Flag_of_Tennessee.svg/46px-Flag_of_Tennessee.svg.png'},{'name':'Texas','flag':'f/f7/Flag_of_Texas.svg/45px-Flag_of_Texas.svg.png'},{'name':'Utah','flag':'f/f6/Flag_of_Utah.svg/45px-Flag_of_Utah.svg.png'},{'name':'Vermont','flag':'4/49/Flag_of_Vermont.svg/46px-Flag_of_Vermont.svg.png'},{'name':'Virginia','flag':'4/47/Flag_of_Virginia.svg/44px-Flag_of_Virginia.svg.png'},{'name':'Washington','flag':'5/54/Flag_of_Washington.svg/46px-Flag_of_Washington.svg.png'},{'name':'West Virginia','flag':'2/22/Flag_of_West_Virginia.svg/46px-Flag_of_West_Virginia.svg.png'},{'name':'Wisconsin','flag':'2/22/Flag_of_Wisconsin.svg/45px-Flag_of_Wisconsin.svg.png'},{'name':'Wyoming','flag':'b/bc/Flag_of_Wyoming.svg/43px-Flag_of_Wyoming.svg.png'}];
});