Pure AngularJS tagging widget with typeahead support courtesy of ui-bootstrap.
0.3.1
bower install angular-tags
- AngularJS
- ui-bootstrap (ui.bootstrap.typeahead module)
- Bootstrap CSS (optional)
- Font Awesome (optional)
Clone this repo and execute:
npm install
to grab the dependencies. Then execute:
grunt test
to run the tests. This will grab the test deps from bower, and run them against QUnit in a local server on port 8000.
angular-tags comes in two versions; one with embedded templates and another without. Without templates:
<script src="/path/to/angular-tags-VERSION.js"></script>
With templates:
<script src="/path/to/angular-tags-VERSION-tpls.js"></script>
You will also want to include the CSS if you are using this version:
<link rel="stylesheet" href="/path/to/angular-tags-VERSION.css"/>
Templates are included in the templates/
directory if you want to load them manually and/or modify them.
You'll also need to make sure you have included the ui-bootstrap source.
Finally, include the module in your code, and the required ui.bootstrap.typeahead
module:
angular.module('myModule', ['decipher.tags', 'ui.bootstrap.typeahead'];
This is a directive, so at its most basic:
<tags model="foo"></tags>
This will render the tags contained in foo
(if anything) and provide an input prompt for more tags.
foo
can be a delimited string, array of strings, or array of objects with name
properties:
foo = 'foo,bar';
foo = ['foo', 'bar'];
foo = [{name: 'foo'}, {name: 'bar'}];
All will render identically. Depending on the format you use, you will get the same type back when adding tags via the input. For example, if you add "baz" in the input and your original model happened to be a delimited string, you will get:
'foo,bar,baz'
Likewise if you had an array of strings:
['foo', 'bar', 'baz']
The above directive usage will not use the typeahead functionality of ui-bootstrap. To use the typehead functionality, which provides a list of tags from which to choose, you have to specify some values to read from:
<tags model="foo" src="b as b.name for b in baz"></tags>
The value of src
is a comprehension expression, like found in ngOptions. baz
here should resemble foo
as above; a delimited string, an array of strings, or an array of objects. See Tag Objects below.
Note: Here we're using b
(the entire object) for the value; feel free to use something else, but if we use b
, the directive will retain any extra data you have put in the tag objects:
baz = [
{foo: 'bar', value: 'baz', name: 'derp'},
{foo: 'spam', value: 'baz', name: 'herp'},
]
and
<tags model="foo" src="b.value as b.name for b in baz"></tags>
The resulting source tags will look like this:
baz = [
{value: 'baz', name: 'derp'},
{value: 'baz', name: 'herp'},
]
Basically, whatever you set here will become the value
of these tags unless you specify an entire object.
You can pass options through to the typeahead module. Simply pass a typeahead-options
attribute to the <tags>
element. Available options are shown here:
$scope.typeaheadOpts = {
inputFormatter: myInputFormatterFunction,
loading: myLoadingBoolean,
minLength: 3,
onSelect: myOnSelectFunction, // this will be run in addition to directive internals
templateUrl: '/path/to/my/template.html',
waitMs: 500,
allowsEditable: true
};
and:
<tags typeahead-options="typeaheadOpts" model="foo" src="b.value as b.name for b in baz"></tags>
Tag objects have three main properties:
name
The name (display name) of the taggroup
(optional) The "group" of the tag, for assigning class namesvalue
(optional) The "value" of the tag, which is not displayed
Tag objects can include any other properties you wish to add.
To set defaults module-wide, inject the decipherTagsOptions
constant into anything and modify it:
myModule.config(function(decipherTagsOptions) {
decipherTagsOptions.delimiter = ':';
decipherTagsOptions.classes = {
myGroup: 'myClass',
myOtherGroup: 'myOtherClass'
};
});
addable
whether or not the user is allowed to type arbitrary tags into the input (defaults tofalse
by default if asrc
is supplied, otherwise defaults totrue
; see Adding Tags below.delimiter
what to use for a delimiter when typing or pasting into the input. Defaults to,
classes
An object mapping of group names to class namestemplateUrl
URL to the main template. Defaults totemplates/tags.html
tagTemplateUrl
URL to the "tag" template. Defaults totemplates/tag.html
If you neglect to supply a src
(thus not using typeahead) you will be able to enter whatever you like into the tags input, adding tags willy-nilly. If you do supply a src
, by default the user will be limited to what's in the list. You can override this by passing an addable
property to the options:
<tags options="{addable: true}" model="foo" src="b as b.name for b in baz"></tags>
If you specify classes, your tags will each be assigned a class name based on the group. For example:
<tags options="{classes: {myGroup: 'myClass'}}" model="foo" src="b as b.name for b in baz></tags>
Now when a tag is added to the list, and that tag has the group
of myGroup
, it will receive the myClass
class. This is useful if you want to change the color of certain tags or something.
The directive will emit certain events based on what's going on:
decipher.tags.initialized
: Emitted when the directive is linked. Data will include a unique$id
value of the directive and the originalmodel
value.decipher.tags.keyup
: Emitted when the user types something into the input. Data will include the unique$id
and thevalue
, which is what the user has typed so far. You can attach to this to do validation or anything else.decipher.tags.added
: Emitted when the user has successfully added a tag. Data will include the unique$id
and atag
object representing the tag added.decipher.tags.addfailed
: Emitted when the user tries to add a tag that is not available for whatever reason. This will occur if the user attempts to add a duplicate tag, or if they attempt to add a tag that is not in the suppliedsrc
list. Data will include the unique$id
and atag
object representing the tag that failed to be added.decipher.tags.removed
: Emitted when the user removes a tag, either via backspacing or clicking on the littlex
in the tag. Data will include the unique$id
and atag
object representing the tag removed.
MIT
Carl Dougan (@carlsgit) and Christopher Hiller (@boneskull)