Swiss-Army-Knife of AngularJS tools (with no external dependencies!)
Bind a callback to any event not natively supported by Angular.
For Blurs, Focus, Double-Clicks or any other event you may choose that isn't built-in.
You can pass multiple events as an object, along with the jQuery event itself:
<input ui-event="{ blur : 'blurCallback($event)' }"> <script> $scope.blurCallback = function(evt) { alert('Goodbye. Input content is: ' + evt.target.value); }; </script>
Replace tokens in a string in a variety of ways
{{ sentence | format : tokens[mode] }}
Tokens: {{ tokens[mode] | json }}
Most commonly, this filter is helpful for internationalization. However anywhere you need to do string replacement the format filter will come in handy.
{{ "Hello $0, how are you?" | format : 'Bob' }} -- or -- $scope.tokens = ['first','second','third']; ... {{ "Are you on the $0, $1 or $2?" | format : tokens }} -- or -- $scope.tokens = { name:'Bob', subject:'wife' }; ... {{ "Hey :name, how's the :subject?" | format : tokens }}
Easily highlight some text in a block
<label><input type="checkbox" ng-model="caseSensitive"> Case Sensitive?</label> <input placeholder="Enter some text to highlight" value="you" ng-model="highlightText"> <p ng-bind-html-unsafe="'Hello there, how are you today? I\'m fine thank you.' | highlight:highlightText:caseSensitive"></p> <style> .ui-match { background: yellow; } </style>
uiInclude
is an alternative to ngInclude
that adds fragment support via a fragment
attribute. The
fragment attribute uses the element.find()
API, and therefore requires jQuery in order to support full CSS
selectors; Without jQuery, it falls back to Angular's jqLite
implementation which is very limited as it only selects by element
name.
Use this instead of ngInclude
only if you need
fragments. Fragment support has two primary uses: (1) it serves as a
drop in replacement for jQuery.load(), which permits a
subset of a requested document to be selected, and (2) because some
people want to put multiple templates into a single file and they need a
way to select which specific fragment to use. The former use is
expected to be benefit projects that are migrating from jQuery to
Angular.
fragment="'{{uiIncludeFragment}}'"
):
<ui-include src="'my/url/to/partial/file'" fragment="'#id-to-fragment'"></ui-include> <!-- Don't forget to quote string literals! --> <!-- Don't forget to include jQuery if you need full selector support! -->
Provides an easy way to toggle a checkbox input's special 'indeterminate' property. This is a visual toggle only and in no way affects the model or value outside of native browser behavior at this time.
Convenience.
Indeterminate: <input type="checkbox" ui-indeterminate="isKnown" readonly> Toggle indeterminate here: <input type="checkbox" ng-model="isKnown">
Converts a string to an alternative format.
{{inflectorText|inflector:inflectorType}}
<label><input type="radio" value="humanize" ng-model="inflectorType"> Humanize (Default)</label> <label><input type="radio" value="underscore" ng-model="inflectorType"> Underscore</label> <label><input type="radio" value="variable" ng-model="inflectorType"> Variable</label> <input placeholder="Enter some text to inflect" ng-model="inflectorText"> <p>{{inflectorText|inflector:inflectorType}}</p> <script> $scope.inflectorText = 'Here Is my_phoneNumber'; $scope.inflectorType = 'humanize'; </script>
Call the jQuery function or plugin specified on the element.
This example shows how to call the bootstrap tooltip with almost no work:
Not every jQuery plugin requires creating a new directive just to use it. Instead, use the pass-through directive to rapidly port functionality. It is probably the best solution for 75% of the cases you will encounter.
If a plugin requires more robust integration with AngularJS then you may need to look into creating a custom directive instead, or contact us with a request.
To call something like $.fn.tooltip()
simply do
ui-jq="tooltip"
. Note that the name of the function must be identical. This also works for normal jQuery commands such as
$.fn.slideUp()
.
To pass parameters use the ui-options
attribute. The value will be evaluated in the
$scope
context and passed to the function. If defaults are set, the passed options will extend them. If a string is passed, the default options will be ignored.
Use the directive name jq
for namespacing inside
uiJqConfig
. Then sub-namespace options for each function by the name of that function (exactly as it is passed to
ui-jq
) so that you don't have to pass options every time you call the directive.
<a title="Easiest. Binding. Ever!" ui-jq="tooltip">Hover over me for static Tooltip</a> <a data-original-title="{{tooltip}}" ui-jq="tooltip">Fill the input for a dynamic Tooltip:</a> <input type="text" ng-model="tooltip" placeholder="Tooltip Content"> <script> myModule.value('uiJqConfig', { // The Tooltip namespace tooltip: { // Tooltip options. This object will be used as the defaults placement: 'right' } }); </script>
Bind an event to a particular keypress
Cuz you feel like it? Maybe I should stop doing the 'Why' sections, running out of explanations...
The directive takes a hash (object) with the key code as the key and the callback function to fire as the value. The callback function takes an 'event' param
Note that 13 represents the RETURN
key code.
<textarea ui-keypress="{13:'keypressCallback($event)'}"> </textarea> <textarea ui-keydown="{'enter alt-space':'keypressCallback($event)'}"> </textarea> <textarea ui-keyup="{'enter':'keypressCallback($event)'}"> </textarea> <div tabindex="0" ui-keyup="{'enter':'keypressCallback($event)'}"> </div> <script> $scope.keypressCallback = function($event) { alert('Voila!'); $event.preventDefault(); }; </script>
TODO !!
Adds an icon or link that empties the input element
Resets to empty:
Resets to "Empty":
Remember that you control the CSS. Make the icon always show by changing the CSS to match the
:hover
state.
You can set an app-wide reset value using ui.config
<input ng-model="resetModel" ui-reset> <input ng-model="resetModel" ui-reset=" 'Empty' "> <script> $scope.resetModel = 'Hover over me'; </script>
Route Matching Magic. It matches your routes ... magically!
Clicking "Make Active" will reload the page. Pay attention to the routes.
It would be nice if your app knew what the address path was and acted accordingly, right? Right.
$uiRoute
.
<a ui-route="/page" ng-class="{active: $uiRoute}">link</a>
ui-route
as an attribute with value supports the following:
<a ui-route="/page">
<a ui-route="/page/[0-9]*">
<a ui-route="/page/{{ sample }}">
<a ui-route="/page/{{ sample }}/[0-9]*">
ui-route
with ng-href
attribute:
<a ui-route ng-href="/page">
<a ui-route ng-href="/page/{{ sample }}">
ui-route
with href
attribute:
<a ui-route href="/page">
ui-route
. This model could then be used the same as
$uiRoute
.
<li ui-route="/page/{{ sample }}" ng-model="current">
<ul> <li ui-route="#/route-1">Route 1 <strong ng-show="$uiRoute">IS</strong> <strong ng-show="!$uiRoute">is NOT</strong> active. </li> <li ui-route="#/route-2">Route 2 <strong ng-show="$uiRoute">IS</strong> <strong ng-show="!$uiRoute">is NOT</strong> active. </li> <li ui-route="#/route-3">Route 3 <strong ng-show="$uiRoute">IS</strong> <strong ng-show="!$uiRoute">is NOT</strong> active. </li> </ul>
Provide access to scrollable lists of unlimited length.
Items can be of any complexity and can vary in any possible way. They are dynamically instantiated as they become visible and $destroyed as they are scrolled out of view.
The common way to present to the user a list of data elements of undefined length is to start with a small portion at the top of the list - just enough to fill the space on the page. Additional rows are appended to the bottom of the list as the user scrolls down the list.
Unfortunately, even though rows at the top of the list become invisible as they scroll out of the view, they are still a part of the page and still consume resources. As the user scrolls down the list grows and the web app slows down.
If all you want to use the entire window as the viewport, all you need is this:
<div ui-scroll="item in datasource">{{item}}</div>
If you want to control the viewport yourself you can do it like this:
<div ui-scroll-viewport style="height:200px;" > <div ui-scroll="item in datasource">{{item}}</div> </div>
Make sure that you always constrain the height of your viewport
Add a 'ui-fixed' class to elements when the page scrolls past them
They see me scrollin...
Try scrolling past the red text or changing the offsetMake elements sticky, or simply appear different after scrolling past a certain point
Remember that this directive
only adds a
ui-scrollfix
class to the element. It is up to you to add the corresponding CSS rules, however it also gives you the ability to add other rules instead if you prefer.
<p ui-scrollfix>They see me scrollin...</p>
You can optionally pass a number to
ui-scrollfix
which would override the detected y-offset of the element. Values can be either absolute
600
or offset from the calculated value -50
or +100
.
Instead of doing ng-show
and ng-hide
which simply sets
display:block/none
a ui-show
and
ui-hide
class will be added which can give you tighter control over how things appear or disappear.
Toggle State: {{!!showHideAn}}
Show Hide Toggle
CSS3 transitions of course! Applying a class means you can specify exactly how these two states behave. In addition, the show/hide variants do not enforce css rules when they are false (unless you use toggle), so the default CSS can still apply.
But can't you just do ng-class="{ ui-show : someExpression }"
?
... shutup.
In all seriousness, this is just a convenience wrapper for using
ng-class
. This way you can simply swap out instances of ng for
ui to immediately get your customized approach.
<p><a ng-click="showHide=!showHide">Toggle State: {{!!showHide}}</a></p> <div ui-show="showHide">Show</div> <div ui-hide="showHide">Hide</div> <div ui-toggle="showHide">Toggle</div> <style> .ui-show { color: blue; transition: all 0.5s ease; /* You should probably browser-prefix this */ } .ui-hide { opacity: 0; transition: all 0.5s ease; /* You should probably browser-prefix this */ } </style>
Using ui-show
or ui-hide
will add a class of the same name when the expression is true.
Use ui-toggle
if you want to leverage both classes, as
ui-show
will be added when true and ui-hide
when false.
Filters out all duplicate objects items from an array by checking the specified key
Select an attribute to check for uniqueness
{{items | unique:attribute | json}}
The filter can take the name of the key to check for uniqueness or set to a non-string truthy value to check the entire object.
<select ng-model="attribute"> <option value="">-- No Filter --</option> <option>firstName</option> <option>lastName</option> <option>id</option> <option>gender</option> </select> <pre>{{items | unique:attribute | json}}</pre> <script> $scope.items = [ { firstName: 'Dean', lastName: 'Sofer', id: 1, gender: 'Male' }, { firstName: 'Dean', lastName: 'Kuntz', id: 2, gender: 'Male' }, { firstName: 'Peter', lastName: 'Piper', id: 3, gender: 'Female' }, { firstName: 'Peter', lastName: 'Darwin', id: 4, gender: 'Male' }, { firstName: 'Janet', lastName: 'Piper', id: 5, gender: 'Female' }, { firstName: 'Dan', lastName: 'Doyon', id: 6, gender: 'Male' }, { firstName: 'Andy', lastName: 'Joslin', id: 1, gender: 'Male' }, ]; </script>
The ui-validate
directive makes it very easy to create custom validator expressions.
AngularJS comes with several built-in validation mechanism for input fields (ngRequired, ngPattern etc.) but using an arbitrary validation function requires creation of custom formatters and / or parsers. The ui-validate directive makes it easy to use any function(s) defined in scope as a validator function(s).
<input name="email" ng-model="email" ui-validate="{blacklist : 'notBlackListed($value)' }"> Is e-mail black-listed? {{!!form.email.$error.blacklist}} <input name="password" required ng-model="password"> <input name="confirm_password" ui-validate=" '$value==password' " ui-validate-watch=" 'password' "> Passwords match? {{!!form.confirm_password.$error.validator}} ... $scope.notBlackListed = function(value) { var blacklist = ['[email protected]','[email protected]']; return blacklist.indexOf(value) === -1; }
Create an expression inside a string. If it evaluates to
true
the input is valid, the rule name will be validator
by default.
ui-validate=" 'validateFoo($value)' " Input is valid: {{!!myForm.myInput.$error.validator}}
Or define multiple rules by creating an object where the key is the rule name and the value is the expression string.
ui-validate="{foo:'valFoo($value)', bar:'$value == someVar'}" Foo rule passes: {{!!myForm.myInput.$error.foo}} Bar rule passes: {{!!myForm.myInput.$error.bar}}