UI Bootstrap

Bootstrap components written in pure AngularJS by the AngularUI Team

Code on Github

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.4.x, tested with 1.4.8). 0.14.3 is the last version of this library that supports AngularJS 1.3.x and 0.12.0 is the last version that supports AngularJS 1.2.x.
  • Bootstrap CSS (tested with version 3.3.6). This version of the library (1.0.3) 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 components provided in ui-bootstrap have documentation and interactive Plunker examples.

For the directives, we list the different attributes with their default values. In addition to this, some settings have a badge on it:

  • - This setting has an angular $watch listener applied to it.
  • B - This setting is a boolean. It doesn't need a parameter.
  • C - This setting can be configured globally in a constant service*.
  • $ - This setting expects an angular expression instead of a literal string. If the expression support a boolean / integer, you can pass it directly.
  • readonly - This setting is readonly.

For the services (you will recognize them with the $ prefix), we list all the possible parameters you can pass to them and their default values if any.

* Some directives have a config service that follows the next pattern: uibDirectiveConfig. The service's settings use camel case. The services can be configured in a .config function for example.

This content is straight in the template. {{group.content}}

The body of the uib-accordion group grows to fit the contents

{{item}}
Hello

Please, to delete your account, click the button below

I can have markup, too! This is just some content to illustrate fancy headings.

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 $ C (Default: true) - 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

  • heading (Default: none) - The clickable text on the group's header. You need one to be able to click on the header for toggling.

  • is-disabled $ (Default: false) - Whether the accordion group is disabled or not.

  • is-open $ (Default: false) - Whether accordion group is open or closed.

  • 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: uib/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.


<style>
  .accordion-toggle {
    cursor: pointer;
  }
</style>

<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.msg}} A happy 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 an alert is closed. If the attribute exists, a close button is displayed as well.

  • dismiss-on-timeout (Default: none) - Takes the number of milliseconds that specify the timeout duration, after which the alert will be closed. This attribute requires the presence of the close attribute.

  • template-url (Default: uib/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);
  };
});

Single toggle

{{singleModel}}

Checkbox

Model: {{checkModel}}
Results: {{checkResults}}

Radio & Uncheckable Radio

{{radioModel || 'null'}}

With the buttons directive, we can make a group of buttons behave like a set of checkboxes (uib-btn-checkbox) or behave like a set of radio buttons (uib-btn-radio).

uib-btn-checkbox settings

  • btn-checkbox-false (Default: false) - Sets the value for the unchecked status.

  • btn-checkbox-true (Default: true) - Sets the value for the checked status.

  • ng-model $ - Model where we set the checkbox status. By default true or false.

uib-btn-radio settings

  • ng-model $ - Model where we set the radio status. All radio buttons in a group should use the same ng-model.

  • uib-btn-radio - $ Value to assign to the ng-model if we check this radio button.

  • uib-uncheckable $ (Default: null) - An expression that evaluates to a truthy or falsy value that determines whether the uncheckable attribute is present.

  • uncheckable B - Whether a radio button can be unchecked or not.

Additional settings uibButtonConfig

  • activeClass (Default: active) - Class to apply to the checked buttons.

  • toggleEvent (Default: click) - Event used to toggle the buttons.


<div ng-controller="ButtonsCtrl">
    <h4>Single toggle</h4>
    <pre>{{singleModel}}</pre>
    <button type="button" class="btn btn-primary" ng-model="singleModel" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
        Single Toggle
    </button>
    <h4>Checkbox</h4>
    <pre>Model: {{checkModel}}</pre>
    <pre>Results: {{checkResults}}</pre>
    <div class="btn-group">
        <label class="btn btn-primary" ng-model="checkModel.left" uib-btn-checkbox>Left</label>
        <label class="btn btn-primary" ng-model="checkModel.middle" uib-btn-checkbox>Middle</label>
        <label class="btn btn-primary" ng-model="checkModel.right" uib-btn-checkbox>Right</label>
    </div>
    <h4>Radio &amp; Uncheckable Radio</h4>
    <pre>{{radioModel || 'null'}}</pre>
    <div class="btn-group">
        <label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Left'">Left</label>
        <label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Middle'">Middle</label>
        <label class="btn btn-primary" ng-model="radioModel" uib-btn-radio="'Right'">Right</label>
    </div>
    <div class="btn-group">
        <label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Left'" uncheckable>Left</label>
        <label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Middle'" uncheckable>Middle</label>
        <label class="btn btn-success" ng-model="radioModel" uib-btn-radio="'Right'" uib-uncheckable="uncheckable">Right</label>
    </div>
    <div>
        <button class="btn btn-default" ng-click="uncheckable = !uncheckable">
            Toggle uncheckable
        </button>
    </div>
</div>
angular.module('ui.bootstrap.demo').controller('ButtonsCtrl', function ($scope) {
  $scope.singleModel = 1;

  $scope.radioModel = 'Middle';

  $scope.checkModel = {
    left: false,
    middle: true,
    right: false
  };

  $scope.checkResults = [];

  $scope.$watchCollection('checkModel', function () {
    $scope.checkResults = [];
    angular.forEach($scope.checkModel, function (value, key) {
      if (value) {
        $scope.checkResults.push(key);
      }
    });
  });
});

Some content

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;
});

Formatting codes playground

The uibDateParser is what the uib-datepicker uses internally to parse the dates. You can use it standalone by injecting the uibDateParser service where you need it.

The public API for the dateParser is a single method called parse.

Certain format codes support i18n. Check this guide for more information.

uibDateParser's parse function

parameters
  • input (Type: string, Example: 2004/Sep/4) - The input date to parse.

  • format (Type: string, Example: yyyy/MMM/d) - The format we want to use. Check all the supported formats below.

  • baseDate (Type: Date, Example: new Date()) - If you want to parse a date but maintain the timezone, you can pass an existing date here.

return
  • If the specified input matches the format, a new date with the input will be returned, otherwise, it will return undefined.

uibDateParser's format codes

  • yyyy (Example: 2015) - Parses a 4 digits year.

  • yy (Example: 15) - Parses a 2 digits year.

  • y (Example: 15) - Parses a year with 1, 2, 3, or 4 digits.

  • MMMM (Example: February, i18n support) - Parses the full name of a month.

  • MMM (Example: Feb, i18n support) - Parses the short name of a month.

  • MM (Example: 12, Leading 0) - Parses a numeric month.

  • M (Example: 3) - Parses a numeric month.

  • M! (Example: 3 or 03) - Parses a numeric month, but allowing an optional leading zero

  • dd (Example: 05, Leading 0) - Parses a numeric day.

  • d (Example: 5) - Parses a numeric day.

  • d! (Example: 3 or 03) - Parses a numeric day, but allowing an optional leading zero

  • EEEE (Example: Sunday, i18n support) - Parses the full name of a day.

  • EEE (Example: Mon, i18n support) - Parses the short name of a day.

  • HH (Example: 14, Leading 0) - Parses a 24 hours time.

  • H (Example: 3) - Parses a 24 hours time.

  • hh (Example: 11, Leading 0) - Parses a 12 hours time.

  • h (Example: 3) - Parses a 12 hours time.

  • mm (Example: 09, Leading 0) - Parses the minutes.

  • m (Example: 3) - Parses the minutes.

  • sss (Example: 094, Leading 0) - Parses the milliseconds.

  • ss (Example: 08, Leading 0) - Parses the seconds.

  • s (Example: 22) - Parses the seconds.

  • a (Example: 10AM) - Parses a 12 hours time with AM/PM.

  • Z (Example: -0800) - Parses the timezone offset in a signed 4 digit representation

  • ww (Example: 03, Leading 0) - Parses the week number

  • w (Example: 03) - Parses the week number

  • G, GG, GGG (Example: AD) - Parses the era (AD or BC)

  • GGGG (Example: Anno Domini) - Parses the long form of the era (Anno Domini or Before Christ)

* The ones marked with Leading 0, needs a leading 0 for values less than 10. Exception being milliseconds which needs it for values under 100.

** It also supports fullDate|longDate|medium|mediumDate|mediumTime|short|shortDate|shortTime as the format for parsing.

*** It supports template literals as a string between the single quote ' character, i.e. 'The Date is' MM/DD/YYYY. If one wants the literal single quote character, one must use ''''.


<div ng-controller="DateParserDemoCtrl">
  <h4>Formatting codes playground</h4>
  <p class="form-group">
    <label>Define your format</label>
    <input type="text" ng-model="format" class="form-control">
  </p>
  <p class="form-group">
    <label>Result</label>
    <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="date" />
  </p>
</div>
angular.module('ui.bootstrap.demo').controller('DateParserDemoCtrl', function ($scope, uibDateParser) {
  $scope.format = 'yyyy/MM/dd';
  $scope.date = new Date();
});
Selected date is: {{dt | date:'fullDate' }}

Inline

Popup


Our datepicker is flexible and fully customizable.

You can navigate through days, months and years.

It comes in two formats, an inline uib-datepicker and an uib-datepicker-popup to be embedded in an input.

The datepicker has 3 modes:

  • day - In this mode you're presented with a 6-week calendar for a specified month.
  • month - In this mode you can select a month within a selected year.
  • year - In this mode you are presented with a range of years (20 by default).

uib-datepicker settings

  • custom-class (date, mode) $ (Default: null) - An optional expression to add classes based on passing a date and current mode.

  • date-disabled (date, mode) $ (Default: null) - An optional expression to disable visible options based on passing a date and current mode.

  • datepicker-mode $ C (Default: day) - Current mode of the datepicker (day|month|year). Can be used to initialize the datepicker in a specific mode.

  • format-day C (Default: dd) - Format of day in month.

  • format-month C (Default: MMMM) - Format of month in year.

  • format-year C (Default: yyyy) - Format of year in year range.

  • format-day-header C (Default: EEE) - Format of day in week header.

  • format-day-title C (Default: MMMM yyyy) - Format of title when selecting day.

  • format-month-title C (Default: yyyy) - Format of title when selecting month.

  • init-date $ (Default: null) - The initial date view when no model value is specified.

  • max-date $ C (Default: null) - Defines the maximum available date.

  • max-mode $ C (Default: year) - Sets an upper limit for mode.

  • min-date $ C (Default: null) - Defines the minimum available date.

  • min-mode $ C (Default: day) - Sets a lower limit for mode.

  • ng-model $ - The date object. Needs to be a Javascript Date object.

  • ng-model-options $ C (Default: {}) - Supported properties:

    • allowInvalid
    • timezone
  • shortcut-propagation $ C (Default: false) - An option to disable the propagation of the keydown event.

  • show-weeks $ C (Default: true) - Whether to display week numbers.

  • starting-day $ C (Default: 0) - Starting day of the week from 0-6 (0=Sunday, ..., 6=Saturday).

  • template-url (Default: uib/template/datepicker/datepicker.html) - Add the ability to override the template used on the component.

  • year-rows $ C (Default: 4) - Number of rows displayed in year selection.

  • year-columns $ C (Default: 5) - Number of columns displayed in year selection.

uib-datepicker-popup settings

Options for the uib-datepicker must be passed as JSON using the datepicker-options attribute. This list is only for popup settings.

  • alt-input-formats $ C (Default: []) - A list of alternate formats acceptable for manual entry.

  • clear-text C (Default: Clear) - The text to display for the clear button.

  • close-on-date-selection $ C (Default: true) - Whether to close calendar when a date is chosen.

  • close-text C (Default: Done) - The text to display for the close button.

  • current-text C (Default: Today) - The text to display for the current day button.

  • datepicker-append-to-body $ C (Default: false, Config: appendToBody) - Append the datepicker popup element to body, rather than inserting after datepicker-popup.

  • datepicker-popup-template-url C (Default: uib/template/datepicker/popup.html) - Add the ability to override the template used on the component.

  • datepicker-template-url C (Default: uib/template/datepicker/datepicker.html) - Add the ability to override the template used on the component (inner uib-datepicker).

  • is-open $ (Default: false) - Whether or not to show the datepicker.

  • on-open-focus $ C (Default: true) - Whether or not to focus the datepicker popup upon opening.

  • show-button-bar $ C (Default: true) - Whether or not to display a button bar underneath the uib-datepicker.

  • type C (Default: text, Config: html5Types) - You can override the input type to be (date|datetime-local|month). That will change the date format of the popup.

  • uib-datepicker-popup C (Default: yyyy-MM-dd, Config: datepickerConfig) - The format for displayed dates. This string can take string literals by surrounding the value with backticks, i.e. yyyy-MM-dd h `o'clock` .

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.

Notes

If the date a user enters falls outside of the min-/max-date range, a dateDisabled validation error will show on the form.


<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="popup1.opened" min-date="minDate" max-date="maxDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
              <span class="input-group-btn">
                <button type="button" class="btn btn-default" ng-click="open1()"><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="popup2.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="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
              </span>
            </p>
        </div>
    </div>
    <div class="row">
        <div class="col-md-6">
            <label>Format: <span class="muted-text">(manual alternate <em>{{altInputFormats[0]}}</em>)</span></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.open1 = function() {
    $scope.popup1.opened = true;
  };

  $scope.open2 = function() {
    $scope.popup2.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.altInputFormats = ['M!/d!/yyyy'];

  $scope.popup1 = {
    opened: false
  };

  $scope.popup2 = {
    opened: false
  };

  var tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  var afterTomorrow = new Date();
  afterTomorrow.setDate(tomorrow.getDate() + 1);
  $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 '';
  };
});

Pager

A lightweight pager directive that is focused on providing previous/next paging functionality

uib-pager settings

  • align C (Default: true) - Whether to align each link to the sides.

  • items-per-page $ C (Default: 10) - Maximum number of items per page. A value less than one indicates all items on one page.

  • next-text C (Default: Next ») - Text for Next button.

  • ng-disabled $ (Default: false) - Used to disable the pager component.

  • ng-model $ - Current page number. First page is 1.

  • num-pages $ readonly (Default: angular.noop) - An optional expression assigned the total number of pages to display.

  • previous-text C (Default: « Previous) - Text for Previous button.

  • template-url (Default: template/pagination/pager.html) - Override the template for the component with a custom provided template.

  • total-items $ - Total number of items in all pages.


<div ng-controller="PagerDemoCtrl">
  <h4>Pager</h4>
  <uib-pager total-items="totalItems" ng-model="currentPage"></uib-pager>
</div>
angular.module('ui.bootstrap.demo').controller('PagerDemoCtrl', function($scope) {
  $scope.totalItems = 64;
  $scope.currentPage = 4;
});

Default

The selected page no: {{currentPage}}

Limit the maximum visible buttons

rotate defaulted to true:
rotate defaulted to true and force-ellipses set to true:
rotate set to false:
boundary-link-numbers set to true and rotate defaulted to true:
boundary-link-numbers set to true and rotate set to false:
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!

uib-pagination settings

  • boundary-links C (Default: false) - Whether to display First / Last buttons.

  • boundary-link-numbers $ C (Default: false) - Whether to always display the first and last page numbers. If max-size is smaller than the number of pages, then the first and last page numbers are still shown with ellipses in-between as necessary. NOTE: max-size refers to the center of the range. This option may add up to 2 more numbers on each side of the displayed range for the end value and what would be an ellipsis but is replaced by a number because it is sequential.

  • direction-links $ C (Default: true) - Whether to display Previous / Next buttons.

  • first-text C (Default: First) - Text for First button.

  • force-ellipses $ C (Default: false) - Also displays ellipses when rotate is true and max-size is smaller than the number of pages.

  • items-per-page $ C (Default: 10) - Maximum number of items per page. A value less than one indicates all items on one page.

  • last-text C (Default: Last) - Text for Last button.

  • max-size $ (Default: null) - Limit number for pagination size.

  • next-text C (Default: Next) - Text for Next button.

  • ng-change $ - This can be used to call a function whenever the page changes.

  • ng-disabled $ (Default: false) - Used to disable the pagination component.

  • ng-model $ - Current page number. First page is 1.

  • num-pages $ readonly (Default: angular.noop) - An optional expression assigned the total number of pages to display.

  • previous-text C (Default: Previous) - Text for Previous button.

  • rotate $ C (Default: true) - Whether to keep current page in the middle of the visible ones.

  • template-url (Default: uib/template/pagination/pagination.html) - Override the template for the component with a custom provided template

  • total-items $ - Total number of items in all pages.


<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="&lsaquo;" next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;"></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>Limit the maximum visible buttons</h4>
    <h6><code>rotate</code> defaulted to <code>true</code>:</h6>
    <uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" num-pages="numPages"></uib-pagination>
    <h6><code>rotate</code> defaulted to <code>true</code> and <code>force-ellipses</code> set to <code>true</code>:</h6>
    <uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" force-ellipses="true"></uib-pagination>
    <h6><code>rotate</code> set to <code>false</code>:</h6>
    <uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" rotate="false"></uib-pagination>
    <h6><code>boundary-link-numbers</code> set to <code>true</code> and <code>rotate</code> defaulted to <code>true</code>:</h6>
    <uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></uib-pagination>
    <h6><code>boundary-link-numbers</code> set to <code>true</code> and <code>rotate</code> set to <code>false</code>:</h6>
    <uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true" rotate="false"></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;
});

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 three versions of the popover: uib-popover and uib-popover-template, and uib-tooltip-html:

  • 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. Note that this HTML is not compiled. If compilation is required, please use the uib-popover-template attribute option instead. The user is responsible for ensuring the content is safe to put into the DOM!
  • uib-popover-template $ - A URL representing the location of a template to use for the popover body. Note that the contents of this template need to be wrapped in a tag, e.g., <div></div>.

uib-popover-* settings

All these settings are available for the three types of popovers.

  • popover-animation $ C (Default: true, Config: animation) - Should it fade in and out?

  • popover-append-to-body $ (Default: false) - Should the popover be appended to '$body' instead of the parent element?

  • popover-is-open (Default: false) - Whether to show the popover.

  • popover-placement C (Default: top, Config: placement) - Passing in 'auto' separated by a space before the placement will enable auto positioning, e.g: "auto bottom-left". The popover will attempt to position where it fits in the closest scrollable ancestor. Accepts:

    • top - popover on top, horizontally centered on host element.
    • top-left - popover on top, left edge aligned with host element left edge.
    • top-right - popover on top, right edge aligned with host element right edge.
    • bottom - popover on bottom, horizontally centered on host element.
    • bottom-left - popover on bottom, left edge aligned with host element left edge.
    • bottom-right - popover on bottom, right edge aligned with host element right edge.
    • left - popover on left, vertically centered on host element.
    • left-top - popover on left, top edge aligned with host element top edge.
    • left-bottom - popover on left, bottom edge aligned with host element bottom edge.
    • right - popover on right, vertically centered on host element.
    • right-top - popover on right, top edge aligned with host element top edge.
    • right-bottom - popover on right, bottom edge aligned with host element bottom edge.
  • popover-popup-close-delay C (Default: 0, Config: popupCloseDelay) - For how long should the popover remain open after the close trigger event?

  • popover-popup-delay C (Default: 0, Config: popupDelay) - Popup delay in milliseconds until it opens.

  • popover-title - A string to display as a fancy title.

  • popover-trigger (Default: mouseenter) - What should trigger a show of the popover? Supports a space separated list of event names (see below).

Note: To configure the tooltips, you need to do it on $uibTooltipProvider (also see below).

Triggers

The following show triggers are supported out of the box, along with their provided hide triggers:

  • mouseenter: mouseleave
  • click: click
  • outsideClick: outsideClick
  • focus: blur
  • none

The outsideClick trigger will cause the popover to toggle on click, and hide when anything else is clicked.

For any non-supported value, the trigger will be used to both show and hide the popover. Using the 'none' trigger will disable the internal trigger(s), one can then use the popover-is-open attribute exclusively to show and hide the popover.

$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) (Example: { 'openTrigger': 'closeTrigger' }) - Extends the default trigger mappings mentioned above with mappings of your own.

  • options(obj) - Provide a set of defaults for certain tooltip and popover attributes. Currently supports the ones with the C badge.

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>
    <div class="form-group">
      <label>Popover placement</label>
      <select class="form-control" ng-model="placement.selected" ng-options="o as o for o in placement.options"></select>
    </div>
    <button popover-placement="{{placement.selected}}" uib-popover="On the {{placement.selected}}" type="button" class="btn btn-default">Popover {{placement.selected}}</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>
    <button uib-popover="I am activated manually" popover-is-open="popoverIsOpen" ng-click="popoverIsOpen = !popoverIsOpen" type="button" class="btn btn-default">Toggle popover</button>
</div>
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope) {
  $scope.dynamicPopover = {
    content: 'Hello, World!',
    templateUrl: 'myPopoverTemplate.html',
    title: 'Title'
  };

  $scope.placement = {
    options: [
      'top',
      'top-left',
      'top-right',
      'bottom',
      'bottom-left',
      'bottom-right',
      'left',
      'left-top',
      'left-bottom',
      'right',
      'right-top',
      'right-bottom'
    ],
    selected: 'top'
  };
});

$uibPosition service

Demo element

offsetParent: {{elemVals.offsetParent}}
scrollParent: {{elemVals.scrollParent}}
scrollbarWidth: {{scrollbarWidth}}
position: {{elemVals.position}}
offset: {{elemVals.offset}}
viewportOffset: {{elemVals.viewportOffset}}
positionElements: {{elemVals.positionElements}}

The $uibPosition service provides a set of DOM utilities used internally to absolute-position an element in relation to another element (tooltips, popovers, typeaheads etc...).

getRawNode(element)

Takes a jQuery/jqLite element and converts it to a raw DOM element.

parameters
  • element (Type: object) - The element to convert.
returns
  • (Type: element) - A raw DOM element.

parseStyle(element)

Parses a numeric style value to a number. Strips units and will return 0 for invalid (NaN) numbers.

parameters
  • value (Type: string) - The style value to parse.
returns
  • (Type: number) - The numeric value of the style property.

offsetParent(element)

Gets the closest positioned ancestor.

parameters
  • element (Type: element) - The element to get the offset parent for.
returns
  • (Type: element) - The closest positioned ancestor.

scrollbarWidth()

Calculates the browser scrollbar width and caches the result for future calls. Concept from the TWBS measureScrollbar() function in modal.js.

returns
  • (Type: number) - The width of the browser scrollbar.

scrollParent(element, includeHidden)

Gets the closest scrollable ancestor. Concept from the jQueryUI scrollParent.js.

parameters
  • element (Type: element) - The element to get the closest scrollable ancestor for.

  • includeHidden (Type: boolean, Default: false, optional) - Should scroll style of 'hidden' be considered.

returns
  • (Type: element) - The closest scrollable ancestor.

position(element, includeMargins)

A read-only equivalent of jQuery's position function, distance to closest positioned ancestor. Does not account for margins by default like jQuery's position.

parameters
  • element (Type: element) - The element to get the position for.

  • includeMargins (Type: boolean, Default: false, optional) - Should margins be accounted for.

returns

An object with the following properties:

  • width (Type: number) - The width of the element.

  • height (Type: number) - The height of the element.

  • top (Type: number) - Distance to top edge of offset parent.

  • left (Type: number) - Distance to left edge of offset parent.

offset(element)

A read-only equivalent of jQuery's offset function, distance to viewport.

parameters
  • element (Type: element) - The element to get the offset for.
returns

An object with the following properties:

  • width (Type: number) - The width of the element.

  • height (Type: number) - The height of the element.

  • top (Type: number) - Distance to top edge of the viewport.

  • left (Type: number) - Distance to left edge of the viewport.

viewportOffset(element, useDocument, includePadding)

Gets the elements available space relative to the closest scrollable ancestor. Accounts for padding, border, and scrollbar width. Right and bottom dimensions represent the distance to the respective edge of the viewport element, not the top and left edge. If the element edge extends beyond the viewport, a negative value will be reported.

parameters
  • element (Type: element) - The element to get the viewport offset for.

  • useDocument (Type: boolean, Default: false, optional) - Should the viewport be the document element instead of the first scrollable element.

  • includePadding (Type: boolean, Default: true, optional) - Should the padding on the viewport element be accounted for, default is true.

returns

An object with the following properties:

  • top (Type: number) - Distance to top content edge of the viewport.

  • bottom (Type: number) - Distance to bottom content edge of the viewport.

  • left (Type: number) - Distance to left content edge of the viewport.

  • right (Type: number) - Distance to right content edge of the viewport.

parsePlacement(placement)

Gets an array of placement values parsed from a placement string. Along with the 'auto' indicator, supported placement strings are:

  • top: element on top, horizontally centered on host element.
  • top-left: element on top, left edge aligned with host element left edge.
  • top-right: element on top, right edge aligned with host element right edge.
  • bottom: element on bottom, horizontally centered on host element.
  • bottom-left: element on bottom, left edge aligned with host element left edge.
  • bottom-right: element on bottom, right edge aligned with host element right edge.
  • left: element on left, vertically centered on host element.
  • left-top: element on left, top edge aligned with host element top edge.
  • left-bottom: element on left, bottom edge aligned with host element bottom edge.
  • right: element on right, vertically centered on host element.
  • right-top: element on right, top edge aligned with host element top edge.
  • right-bottom: element on right, bottom edge aligned with host element bottom edge.

A placement string with an 'auto' indicator is expected to be space separated from the placement, i.e: 'auto bottom-left'. If the primary and secondary placement values do not match 'top, bottom, left, right' then 'top' will be the primary placement and 'center' will be the secondary placement. If 'auto' is passed, true will be returned as the 3rd value of the array.

parameters
  • placement (Type: string, Example: auto top-left) - The placement string to parse.
returns

An array with the following values:

  • [0] (Type: string) - The primary placement.

  • [1] (Type: string) - The secondary placement.

  • [2] (Type: boolean) - Is auto place enabled.

positionElements(hostElement, targetElement, placement, appendToBody)

Gets gets coordinates for an element to be positioned relative to another element.

parameters
  • hostElement (Type: element) - The element to position against.

  • targetElement (Type: element) - The element to position.

  • placement (Type: string, Default: top, optional) - The placement for the target element. See the parsePlacement() function for available options. If 'auto' placement is used, the viewportOffset() function is used to decide where the targetElement will fit.

  • appendToBody (Type: boolean, Default: false, optional) - Should the coordinates be cacluated from the body element.

returns

An object with the following properties:

  • top (Type: number) - The targetElement top value.

  • left (Type: number) - The targetElement left value.

  • right (Type: number) - The resolved placement with 'auto' removed.

positionArrow(element, placement)

Positions the tooltip and popover arrow elements when using placement options beyond the standard top, left, bottom, or right.

parameters
  • element (Type: element) - The element to position the arrow element for.

  • placement (Type: string) - The placement for the element.


<div ng-controller="PositionDemoCtrl">
  <h4>$uibPosition service</h4>
  <div id="posdemoparent" ng-style="{'overflow': (parentScrollable && 'scroll'), 'position': (parentRelative && 'relative')}" style="border: 1px solid #ccc; padding: 15px;">
    <div class="checkbox">
      <label>
        <input type="checkbox" ng-model="parentScrollable"> Parent scrollable
      </label>
    </div>
    <div class="checkbox">
      <label>
        <input type="checkbox" ng-model="parentRelative"> Parent relative
      </label>
    </div>
    <button id="posdemobtn" class="btn btn-default" ng-click="getValues()">Get values</button>

    <div id="posdemodiv" style="width: 100px; height: 100px; margin: 15px 0; padding: 10px; background-color: #f8f8f8; border: 1px solid #ccc;">
      Demo element
    </div>
  </div>
  <br />
  offsetParent: {{elemVals.offsetParent}}
  <br />
  scrollParent: {{elemVals.scrollParent}}
  <br />
  scrollbarWidth: {{scrollbarWidth}}
  <br />
  position: {{elemVals.position}}
  <br />
  offset: {{elemVals.offset}}
  <br />
  viewportOffset: {{elemVals.viewportOffset}}
  <br />
  positionElements: {{elemVals.positionElements}}
</div>
angular.module('ui.bootstrap.demo').controller('PositionDemoCtrl', function ($scope, $window, $uibPosition) {

    $scope.elemVals = {};
    $scope.parentScrollable = true;
    $scope.parentRelative = true;

    $scope.getValues = function() {
      var divEl = $window.document.querySelector('#posdemodiv');
      var btnEl = $window.document.querySelector('#posdemobtn');

      var offsetParent = $uibPosition.offsetParent(divEl);
      $scope.elemVals.offsetParent = 'type: ' + offsetParent.tagName + ', id: ' + offsetParent.id;

      var scrollParent = $uibPosition.scrollParent(divEl);
      $scope.elemVals.scrollParent = 'type: ' + scrollParent.tagName + ', id: ' + scrollParent.id;

      $scope.scrollbarWidth = $uibPosition.scrollbarWidth();

      $scope.elemVals.position = $uibPosition.position(divEl);

      $scope.elemVals.offset = $uibPosition.offset(divEl);

      $scope.elemVals.viewportOffset = $uibPosition.viewportOffset(divEl);

      $scope.elemVals.positionElements = $uibPosition.positionElements(btnEl, divEl, 'auto bottom-left');
    };
});

Static

22%
166 / 200

Dynamic

{{dynamic}} / {{max}} No animation {{dynamic}}% Object (changes type based on value) {{type}} !!! Watch out !!!

Stacked

{{bar.value}}%

A progress bar directive that is focused on providing feedback on the progress of a workflow or action.

It supports multiple (stacked) <uib-bar> into the same <uib-progress> element or a single <uib-progressbar> element with optional max attribute and transition animations.

uib-progressbar settings

  • value $ - The current value of progress completed.

  • type (Default: null) - Bootstrap style type. Possible values are 'success', 'info', 'warning', and, 'error' to use Bootstrap's pre-existing styling, or any desired custom suffix.

  • max $ C (Default: 100) - A number that specifies the total value of bars that is required.

  • animate $ C (Default: true) - Whether bars use transitions to achieve the width change.

  • title (Default: progressbar) - Title to use as label (for accessibility).

uib-progress settings

  • max $ C (Default: 100) - A number that specifies the total value of bars that is required.

  • animate $ C (Default: true) - Whether bars use transitions to achieve the width change.

  • title (Default: progressbar) - Title to use as label (for accessibility).

uib-bar settings

  • value $ - The current value of progress completed.

  • type (Default: null) - Bootstrap style type. Possible values are 'success', 'info', 'warning', and, 'error' to use Bootstrap's pre-existing styling, or any desired custom suffix.

  • title (Default: progressbar) - Title to use as label (for accessibility).


<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();
});

Default

{{percent}}%
Rate: {{rate}} - Readonly is: {{isReadonly}} - Hovering over: {{overStar || "none"}}

Custom icons

(Rate: {{x}})
(Rate: {{y}})

Rating directive that will take care of visualising a star rating bar.

uib-rating settings

  • max $ C (Default: 5) - Changes the number of icons.

  • ng-model $ - The current rate.

  • on-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.

  • rating-states $ (Default: null) - An array of objects defining properties for all icons. In default template, stateOn & stateOff property is used to specify the icon's class.

  • readonly $ (Default: false) - Prevent user's interaction.

  • titles $ C (Default: ['one', 'two', 'three', 'four', 'five']`) - An array of strings defining titles for all icons.

  • state-off $ C (Default: null) - A variable used in the template to specify the state for unselected icons.

  • state-on $ C (Default: null) - A variable used in the template to specify the state (class, src, etc) for selected icons.


<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'}
  ];
});

Select a tab by setting active binding to true:


Static content {{tab.content}} Alert! I've got an HTML heading, and a select callback. Pretty cool!
Vertical content 1 Vertical content 2
Justified content Short Labeled Justified content Long Labeled Justified content
Tabs using nested forms:
Some Tab Content More Tab Content
Model:
{{ model | json }}
Nested Form:
{{ outerForm.nestedForm | json }}

AngularJS version of the tabs directive.

uib-tabset settings

  • justified $ (Default: false) - Whether tabs fill the container and have a consistent width.

  • type (Defaults: tabs) - Navigation type. Possible values are 'tabs' and 'pills'.

  • vertical $ (Default: false) - Whether tabs appear vertically stacked.

uib-tab settings

  • active $ (Default: false) - Whether tab is currently selected.

  • deselect() $ (Default: null) - An optional expression called when tab is deactivated.

  • disable $ (Default: false) - Whether tab is clickable and can be activated.

  • heading - Heading text.

  • select() $ (Default: null) - An optional expression called when tab is activated.

Tabset heading

Instead of the heading attribute on the uib-tabset, you can use an uib-tab-heading element inside a tabset that will be used as the tabset's header. There you can use HTML as well.


<style type="text/css">
  form.tab-form-demo .tab-pane {
    margin: 20px 20px;
  }
</style>

<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>

  <hr />

  Tabs using nested forms:
  <form name="outerForm" class="tab-form-demo">
    <uib-tabset>
      <uib-tab heading="Form Tab">
        <ng-form name="nestedForm">
          <div class="form-group">
            <label>Name</label>
            <input type="text" class="form-control" required ng-model="model.name"/>
          </div>
        </ng-form>
      </uib-tab>
      <uib-tab heading="Tab One">
        Some Tab Content
      </uib-tab>
      <uib-tab heading="Tab Two">
        More Tab Content
      </uib-tab>
    </uib-tabset>
  </form>
  Model:
  <pre>{{ model | json }}</pre>
  Nested Form:
  <pre>{{ outerForm.nestedForm | json }}</pre>
</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!');
    });
  };

  $scope.model = {
    name: 'Tabs'
  };
});
Time is: {{mytime | date:'shortTime' }}
Hours step is:
Minutes step is:

A lightweight & configurable timepicker directive.

uib-timepicker settings

  • arrowkeys $ C (Default: true) - Whether user can use up/down arrow keys inside the hours & minutes input to increase or decrease its values.

  • hour-step $ C (Default: 1) - Number of hours to increase or decrease when using a button.

  • max $ (Default: undefined) - Maximum time a user can select.

  • meridians $ C (Default: null) - Meridian labels based on locale. To override you must supply an array like ['AM', 'PM'].

  • min $ (Default: undefined) - Minimum time a user can select

  • minute-step $ C (Default: 1) - Number of minutes to increase or decrease when using a button.

  • mousewheel $ C (Default: true) - Whether user can scroll inside the hours & minutes input to increase or decrease its values.

  • ng-disabled $ (Default: false) - Whether or not to disable the component.

  • ng-model $ - Date object that provides the time state.

  • readonly-input $ C (Default: false) - Whether user can type inside the hours & minutes input.

  • second-step $ C (Default: 1) - Number of seconds to increase or decrease when using a button.

  • show-meridian $ C (Default: true) - Whether to display 12H or 24H mode.

  • show-seconds $ C (Default: false) - Show seconds input.

  • show-spinners $ C (Default: true) - Show spinner arrows above and below the inputs.

  • tabindex (Defaults: 0) - Sets tabindex for each control in the timepicker.

  • template-url C (Defaults: uib/template/timepicker/timepicker.html) - Add the ability to override the template used on the component.


<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;
  };
});

Pellentesque {{dynamicTooltipText}}, sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in aliquam. Tincidunt lobortis feugiat vivamus at fading eget arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur show delay nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas hide delay pharetra convallis posuere morbi leo urna, Custom template at elementum eu, facilisis sed odio morbi quis commodo odio.

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:

  • uib-tooltip - Takes text only and will escape any HTML provided.
  • uib-tooltip-html $ - Takes an expression that evaluates to an HTML string. Note that this HTML is not compiled. If compilation is required, please use the uib-tooltip-template attribute option instead. The user is responsible for ensuring the content is safe to put into the DOM!
  • 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-* settings

All these settings are available for the three types of tooltips.

  • tooltip-animation $ C (Default: true, Config: animation) - Should it fade in and out?

  • tooltip-append-to-body $ (Default: false) - Should the tooltip be appended to '$body' instead of the parent element?

  • tooltip-class - Custom class to be applied to the tooltip.

  • tooltip-enable $ (Default: true) - Is it enabled? It will enable or disable the configured tooltip-trigger.

  • tooltip-is-open (Default: false) - Whether to show the tooltip.

  • tooltip-placement C (Default: top, Config: placement) - Passing in 'auto' separated by a space before the placement will enable auto positioning, e.g: "auto bottom-left". The tooltip will attempt to position where it fits in the closest scrollable ancestor. Accepts:

    • top - tooltip on top, horizontally centered on host element.
    • top-left - tooltip on top, left edge aligned with host element left edge.
    • top-right - tooltip on top, right edge aligned with host element right edge.
    • bottom - tooltip on bottom, horizontally centered on host element.
    • bottom-left - tooltip on bottom, left edge aligned with host element left edge.
    • bottom-right - tooltip on bottom, right edge aligned with host element right edge.
    • left - tooltip on left, vertically centered on host element.
    • left-top - tooltip on left, top edge aligned with host element top edge.
    • left-bottom - tooltip on left, bottom edge aligned with host element bottom edge.
    • right - tooltip on right, vertically centered on host element.
    • right-top - tooltip on right, top edge aligned with host element top edge.
    • right-bottom - tooltip on right, bottom edge aligned with host element bottom edge.
  • tooltip-popup-close-delay C (Default: 0, Config: popupCloseDelay) - For how long should the tooltip remain open after the close trigger event?

  • tooltip-popup-delay C (Default: 0, Config: popupDelay) - Popup delay in milliseconds until it opens.

  • tooltip-trigger (Default: mouseenter) - What should trigger a show of the tooltip? Supports a space separated list of event names (see below).

Note: To configure the tooltips, you need to do it on $uibTooltipProvider (also see below).

Triggers

The following show triggers are supported out of the box, along with their provided hide triggers:

  • mouseenter: mouseleave
  • click: click
  • outsideClick: outsideClick
  • focus: blur
  • none

The outsideClick trigger will cause the tooltip to toggle on click, and hide when anything else is clicked.

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) (Example: { 'openTrigger': 'closeTrigger' }) - Extends the default trigger mappings mentioned above with mappings of your own.

  • options(obj) - Provide a set of defaults for certain tooltip and popover attributes. Currently supports the ones with the C badge.

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>Tooltip placement</label>
      <select class="form-control" ng-model="placement.selected" ng-options="o as o for o in placement.options"></select>
    </div>
    <button tooltip-placement="{{placement.selected}}" uib-tooltip="On the {{placement.selected}}" type="button" class="btn btn-default">Tooltip {{placement.selected}}</button>

    <hr />
    <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-animation="false" uib-tooltip="I don't fade. :-(">fading</a>
      eget arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur
      <a href="#" tooltip-popup-delay='1000' uib-tooltip='appears with delay'>show delay</a>
      nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
      <a href="#" tooltip-popup-close-delay='1000' uib-tooltip='hides with delay'>hide delay</a>
      pharetra convallis posuere morbi leo urna,
      <a href="#" uib-tooltip-template="'myTooltipTemplate.html'">Custom template</a>
      at elementum eu, facilisis sed odio morbi quis commodo odio.
    </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>


    <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>
    <div class="form-group">
      <label>
        Open tooltips <span uib-tooltip="Hello!" tooltip-is-open="tooltipIsOpen" tooltip-placement="bottom">conditionally.</span>
      </label>
      <button ng-click="tooltipIsOpen = !tooltipIsOpen">Toggle tooltip</button>
    </div>
    <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>!');
  $scope.placement = {
    options: [
      'top',
      'top-left',
      'top-right',
      'bottom',
      'bottom-left',
      'bottom-right',
      'left',
      'left-top',
      'left-bottom',
      'right',
      'right-top',
      'right-bottom'
    ],
    selected: 'top'
  };
});

Static arrays

Model: {{selected | json}}

Asynchronous results

Model: {{asyncSelected | json}}
No Results Found

ngModelOptions support

Model: {{ngModelOptionsSelected | 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.

uib-typeahead settings

  • ng-model $ - Assignable angular expression to data-bind to.

  • ng-model-options $ - Options for ng-model (see ng-model-options directive). Currently supports the debounce and getterSetter options.

  • typeahead-append-to $ (Default: null) - Should the typeahead popup be appended to an element instead of the parent element?

  • typeahead-append-to-body $ (Default: false) - Should the typeahead popup be appended to $body instead of the parent element?

  • typeahead-editable $ (Default: true) - Should it restrict model values to the ones selected from the popup only?

  • typeahead-focus-first $ (Default: true) - Should the first match automatically be focused as you type?

  • typeahead-focus-on-select (Default: true) - On selection, focus the input element the typeahead directive is associated with.

  • typeahead-input-formatter (Default: undefined) - Format the ng-model result after selection.

  • typeahead-is-open $ (Default: angular.noop) - Binding to a variable that indicates if the dropdown is open.

  • typeahead-loading $ (Default: angular.noop) - Binding to a variable that indicates if matches are being retrieved asynchronously.

  • typeahead-min-length $ (Default: 1) - Minimal no of characters that needs to be entered before typeahead kicks-in. Must be greater than or equal to 0.

  • typeahead-no-results $ (Default: angular.noop) - Binding to a variable that indicates if no matching results were found.

  • typeahead-on-select($item, $model, $label, $event) $ (Default: null) - A callback executed when a match is selected. $event can be undefined if selection not triggered from a user event.

  • typeahead-popup-template-url (Default: uib/template/typeahead/typeahead-popup.html) - Set custom popup template.

  • typeahead-select-on-blur $ (Default: false) - On blur, select the currently highlighted match.

  • typeahead-select-on-exact $ (Default: false) - Should it automatically select an item when there is one option that exactly matches the user input?

  • typeahead-show-hint $ (Default: false) - Should input show hint that matches the first option?

  • typeahead-template-url (Default: uib/template/typeahead/typeahead-match.html) - Set custom item template.

  • typeahead-wait-ms $ (Default: 0) - Minimal wait time after last character typed before typeahead kicks-in.

  • uib-typeahead $ - Comprehension Angular expression (see select directive).


<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>ngModelOptions support</h4>
    <pre>Model: {{ngModelOptionsSelected | json}}</pre>
    <input type="text" ng-model="ngModelOptionsSelected" ng-model-options="modelOptions" uib-typeahead="state for state in states | filter:$viewValue | limitTo:8" class="form-control">

    <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" typeahead-show-hint="true" typeahead-min-length="0">

    <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) {

  var _selected;

  $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.ngModelOptionsSelected = function(value) {
    if (arguments.length) {
      _selected = value;
    } else {
      return _selected;
    }
  };

  $scope.modelOptions = {
    debounce: {
      default: 500,
      blur: 250
    },
    getterSetter: true
  };

  $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'}];
});