ng2-tag-input
Advanced tools
Comparing version 0.3.4 to 0.3.5
@@ -1,2 +0,2 @@ | ||
export declare const TagInputModule: any; | ||
export declare const TagInputComponent: any; | ||
export { TagInputModule } from './modules/ng2-tag-input.module'; | ||
export { TagInputComponent } from './modules/components/tag-input'; |
"use strict"; | ||
var components = require('./ng2-tag-input.bundle.js'); | ||
exports.TagInputModule = components.TagInputModule; | ||
exports.TagInputComponent = components.TagInputComponent; | ||
var ng2_tag_input_module_1 = require('./modules/ng2-tag-input.module'); | ||
exports.TagInputModule = ng2_tag_input_module_1.TagInputModule; | ||
var tag_input_1 = require('./modules/components/tag-input'); | ||
exports.TagInputComponent = tag_input_1.TagInputComponent; | ||
//# sourceMappingURL=index.js.map |
export declare class DeleteIconComponent { | ||
ngOnInit(): void; | ||
} |
export * from './icon'; |
export * from './tag-input'; |
import { ElementRef, EventEmitter, Renderer, OnInit } from '@angular/core'; | ||
import { TagInputAccessor } from './accessor'; | ||
import { TagInputAccessor } from './helpers/accessor'; | ||
import { TagInputForm } from './tag-input-form/tag-input-form.component'; | ||
export declare class TagInputComponent extends TagInputAccessor implements OnInit { | ||
@@ -19,2 +20,3 @@ private element; | ||
}; | ||
theme: string; | ||
onAdd: EventEmitter<string>; | ||
@@ -27,14 +29,7 @@ onRemove: EventEmitter<string>; | ||
dropdown: any; | ||
itemsMatching: any[]; | ||
inputForm: TagInputForm; | ||
itemsMatching: string[]; | ||
selectedTag: string; | ||
private hasTemplate; | ||
private tagElements; | ||
input: { | ||
element: HTMLElement; | ||
isFocused: boolean; | ||
focus: () => void; | ||
blur: () => void; | ||
}; | ||
private listeners; | ||
private form; | ||
constructor(element: ElementRef, renderer: Renderer); | ||
@@ -46,8 +41,10 @@ removeItem(item: string): void; | ||
handleKeydown($event: any, item: string): void; | ||
readonly errors: string[]; | ||
private setInputValue(value); | ||
private getControl(); | ||
private focus(); | ||
private blur(); | ||
focus(): void; | ||
blur(): void; | ||
hasErrors(): boolean; | ||
isInputFocused(): boolean; | ||
private readonly maxItemsReached; | ||
private hasCustomTemplate(); | ||
ngOnInit(): void; | ||
@@ -54,0 +51,0 @@ ngAfterViewChecked(): void; |
@@ -18,8 +18,8 @@ "use strict"; | ||
var forms_1 = require('@angular/forms'); | ||
var constants_1 = require('./constants'); | ||
var events_actions_1 = require('./events-actions'); | ||
var constants_1 = require('./helpers/constants'); | ||
var events_actions_1 = require('./helpers/events-actions'); | ||
var ng2_material_dropdown_1 = require('ng2-material-dropdown'); | ||
var accessor_1 = require('./accessor'); | ||
var keypress_actions_1 = require('./keypress-actions'); | ||
var input_manager_1 = require('./input-manager'); | ||
var accessor_1 = require('./helpers/accessor'); | ||
var keypress_actions_1 = require('./helpers/keypress-actions'); | ||
var tag_input_form_component_1 = require('./tag-input-form/tag-input-form.component'); | ||
var TagInputComponent = (function (_super) { | ||
@@ -42,2 +42,3 @@ __extends(TagInputComponent, _super); | ||
this.errorMessages = {}; | ||
this.theme = 'default'; | ||
this.onAdd = new core_1.EventEmitter(); | ||
@@ -49,3 +50,2 @@ this.onRemove = new core_1.EventEmitter(); | ||
this.itemsMatching = []; | ||
this.input = Object.create(input_manager_1.input); | ||
this.listeners = (_a = {}, | ||
@@ -60,3 +60,3 @@ _a[constants_1.KEYDOWN] = [], | ||
TagInputComponent.prototype.removeItem = function (item) { | ||
this.items = this.items.filter(function (_item) { return _item !== item; }).slice(0); | ||
this.items = this.items.filter(function (_item) { return _item !== item; }); | ||
if (this.selectedTag === item) { | ||
@@ -73,5 +73,5 @@ this.selectedTag = undefined; | ||
} | ||
var item = this.setInputValue(this.form.value.item); | ||
var item = this.setInputValue(this.inputForm.value.value); | ||
var isDupe = this.items.indexOf(item) !== -1; | ||
var isValid = this.form.valid && | ||
var isValid = this.inputForm.form.valid && | ||
isDupe === false && | ||
@@ -105,12 +105,2 @@ !this.maxItemsReached && | ||
}; | ||
Object.defineProperty(TagInputComponent.prototype, "errors", { | ||
get: function () { | ||
var _this = this; | ||
return Object.keys(this.errorMessages) | ||
.filter(function (err) { return _this.form.get('item').hasError(err); }) | ||
.map(function (err) { return _this.errorMessages[err]; }); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
TagInputComponent.prototype.setInputValue = function (value) { | ||
@@ -123,13 +113,25 @@ var item = value ? this.transform(value) : ''; | ||
TagInputComponent.prototype.getControl = function () { | ||
return this.form.get('item'); | ||
return this.inputForm.value; | ||
}; | ||
TagInputComponent.prototype.focus = function () { | ||
if (this.readonly || this.input.isFocused) { | ||
if (this.readonly || this.inputForm.isInputFocused()) { | ||
return; | ||
} | ||
this.input.focus.call(this); | ||
this.selectItem(undefined); | ||
this.inputForm.focus(); | ||
this.onFocus.emit(this.inputForm.value.value); | ||
}; | ||
TagInputComponent.prototype.blur = function () { | ||
this.input.blur.call(this); | ||
var _this = this; | ||
if (this.autocomplete) { | ||
setTimeout(function () { return _this.dropdown.hide(); }, 150); | ||
} | ||
this.onBlur.emit(this.inputForm.form.value.value); | ||
}; | ||
TagInputComponent.prototype.hasErrors = function () { | ||
return this.inputForm && this.inputForm.hasErrors() ? true : false; | ||
}; | ||
TagInputComponent.prototype.isInputFocused = function () { | ||
return this.inputForm && this.inputForm.isInputFocused() ? true : false; | ||
}; | ||
Object.defineProperty(TagInputComponent.prototype, "maxItemsReached", { | ||
@@ -142,2 +144,8 @@ get: function () { | ||
}); | ||
TagInputComponent.prototype.hasCustomTemplate = function () { | ||
if (!this.template.nativeElement) { | ||
return false; | ||
} | ||
return this.template.nativeElement.children.length > 0; | ||
}; | ||
TagInputComponent.prototype.ngOnInit = function () { | ||
@@ -151,30 +159,16 @@ events_actions_1.addListener.call(this, constants_1.KEYDOWN, events_actions_1.backSpaceListener); | ||
} | ||
this.form = new forms_1.FormGroup({ | ||
item: new forms_1.FormControl('', forms_1.Validators.compose(this.validators)) | ||
}); | ||
}; | ||
TagInputComponent.prototype.ngAfterViewChecked = function () { | ||
this.input.element = this.input.element || this.element.nativeElement.querySelector('input'); | ||
this.tagElements = this.element.nativeElement.querySelectorAll('.tag'); | ||
}; | ||
TagInputComponent.prototype.ngAfterViewInit = function () { | ||
var vm = this; | ||
vm.hasTemplate = vm.template && vm.template.nativeElement.childElementCount > 0; | ||
if (vm.hasTemplate) { | ||
var el = vm.element.nativeElement; | ||
var form = el.querySelector('form'); | ||
var customTagsContainer = el.querySelector('.tags-container--custom'); | ||
var defaultTagsContainer = el.querySelector('.tags-container--default'); | ||
vm.renderer.invokeElementMethod(customTagsContainer, 'appendChild', [form]); | ||
if (defaultTagsContainer) { | ||
vm.renderer.invokeElementMethod(defaultTagsContainer, 'remove', []); | ||
} | ||
var _this = this; | ||
if (this.autocomplete) { | ||
events_actions_1.addListener.call(this, constants_1.KEYUP, events_actions_1.autoCompleteListener); | ||
this.dropdown.onItemClicked.subscribe(events_actions_1.onAutocompleteItemClicked.bind(this)); | ||
this.dropdown.onHide.subscribe(function () { return _this.itemsMatching = []; }); | ||
} | ||
if (vm.autocomplete) { | ||
events_actions_1.addListener.call(vm, constants_1.KEYUP, events_actions_1.autoCompleteListener); | ||
vm.dropdown.onItemClicked.subscribe(events_actions_1.onAutocompleteItemClicked.bind(vm)); | ||
vm.dropdown.onHide.subscribe(function () { | ||
vm.itemsMatching = []; | ||
}); | ||
} | ||
this.inputForm.onKeydown.subscribe(function (event) { | ||
_this.fireEvents('keydown', event); | ||
}); | ||
}; | ||
@@ -226,2 +220,6 @@ __decorate([ | ||
__decorate([ | ||
core_1.Input(), | ||
__metadata('design:type', String) | ||
], TagInputComponent.prototype, "theme", void 0); | ||
__decorate([ | ||
core_1.Output(), | ||
@@ -254,2 +252,6 @@ __metadata('design:type', Object) | ||
], TagInputComponent.prototype, "dropdown", void 0); | ||
__decorate([ | ||
core_1.ViewChild(tag_input_form_component_1.TagInputForm), | ||
__metadata('design:type', tag_input_form_component_1.TagInputForm) | ||
], TagInputComponent.prototype, "inputForm", void 0); | ||
TagInputComponent = __decorate([ | ||
@@ -263,4 +265,4 @@ core_1.Component({ | ||
}], | ||
styles: [require('./style.scss').toString()], | ||
template: require('./template.html') | ||
styles: [require('./tag-input.style.scss').toString()], | ||
template: require('./tag-input.template.html') | ||
}), | ||
@@ -267,0 +269,0 @@ __metadata('design:paramtypes', [core_1.ElementRef, core_1.Renderer]) |
export declare class TagInputModule { | ||
} |
@@ -10,3 +10,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
root["ng2-tag-input"] = factory(root["@angular/core"], root["@angular/forms"], root["@angular/common"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_7__, __WEBPACK_EXTERNAL_MODULE_20__) { | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_7__, __WEBPACK_EXTERNAL_MODULE_22__) { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
@@ -60,3 +60,3 @@ /******/ // The module cache | ||
__webpack_require__(1); | ||
__webpack_require__(20); | ||
__webpack_require__(22); | ||
module.exports = __webpack_require__(7); | ||
@@ -81,6 +81,6 @@ | ||
/***/ 20: | ||
/***/ 22: | ||
/***/ function(module, exports) { | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_20__; | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_22__; | ||
@@ -87,0 +87,0 @@ /***/ } |
@@ -1,3 +0,4 @@ | ||
const components = require('./ng2-tag-input.bundle.js'); | ||
export const TagInputModule = components.TagInputModule; | ||
export const TagInputComponent = components.TagInputComponent; | ||
export { TagInputModule } from './modules/ng2-tag-input.module'; | ||
export { TagInputComponent } from './modules/components/tag-input'; | ||
{ | ||
"name": "ng2-tag-input", | ||
"version": "0.3.4", | ||
"version": "0.3.5", | ||
"description": "Tag Input component for Angular 2", | ||
@@ -20,6 +20,2 @@ "scripts": { | ||
"devDependencies": { | ||
"@types/es6-collections": "^0.5.29", | ||
"@types/es6-shim": "0.0.22-alpha", | ||
"@types/jasmine": "^2.2.34", | ||
"@types/node": "^6.0.39", | ||
"@angular/common": "2.0.0", | ||
@@ -32,2 +28,6 @@ "@angular/compiler": "2.0.0", | ||
"@angular/platform-browser-dynamic": "2.0.0", | ||
"@types/es6-collections": "^0.5.29", | ||
"@types/es6-shim": "0.0.22-alpha", | ||
"@types/jasmine": "^2.2.34", | ||
"@types/node": "^6.0.39", | ||
"autoprefixer": "^6.3.7", | ||
@@ -68,3 +68,3 @@ "awesome-typescript-loader": "1.1.1", | ||
"dependencies": { | ||
"ng2-material-dropdown": "^0.3.4" | ||
"ng2-material-dropdown": "^0.3.6" | ||
}, | ||
@@ -84,3 +84,3 @@ "keywords": [ | ||
"homepage": "https://github.com/Gbuomprisco/ng2-tag-input", | ||
"main": "./dist/index.js", | ||
"main": "./dist/ng2-tag-input.bundle.js", | ||
"files": [ | ||
@@ -87,0 +87,0 @@ "dist", |
259
README.md
@@ -17,41 +17,45 @@ # Angular2 Tag Input [![Build Status](https://travis-ci.org/Gbuomprisco/ng2-tag-input.svg?branch=develop)](https://travis-ci.org/Gbuomprisco/ng2-tag-input) | ||
## Angular 2 Configuration (RC.6) | ||
The component is updated to use the latest version of Angular 2 (RC 5). This means | ||
## Set up the module | ||
The component is updated to use the latest version of Angular 2. This means | ||
it requires some configuration to correctly work with your app. Ensure, you are | ||
registering the following providers when bootstrapping the app: | ||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | ||
import { FormsModule } from '@angular/forms'; | ||
import { App } from './home/home'; | ||
```javascript | ||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | ||
import { FormsModule } from '@angular/forms'; | ||
import { App } from './home/home'; | ||
import { NgModule } from '@angular/core'; | ||
import { BrowserModule } from '@angular/platform-browser'; | ||
import { NgModule } from '@angular/core'; | ||
import { BrowserModule } from '@angular/platform-browser'; | ||
@NgModule({ | ||
imports: [BrowserModule, FormsModule], | ||
bootstrap: [App], | ||
declarations: [App] | ||
}) | ||
export class AppModule {} | ||
@NgModule({ | ||
imports: [BrowserModule, FormsModule], | ||
bootstrap: [App], | ||
declarations: [App] | ||
}) | ||
export class AppModule {} | ||
platformBrowserDynamic().bootstrapModule(AppModule); | ||
platformBrowserDynamic().bootstrapModule(AppModule); | ||
``` | ||
Please do have a look at the file `demo/app.ts` if you are unsure how to configure the app. | ||
## Usage | ||
## Configuration | ||
Ensure you import the module: | ||
import { TagInputModule } from 'ng2-tag-input'; | ||
```javascript | ||
import { TagInputModule } from 'ng2-tag-input'; | ||
// please notice this is the new way of telling a Component | ||
// to import another component...no more directives[] | ||
@NgModule({ | ||
imports: [TagInputModule] | ||
}) | ||
export class MyModule {} | ||
// please notice this is the new way of telling a Component | ||
// to import another component...no more directives[] | ||
@NgModule({ | ||
imports: [TagInputModule] | ||
}) | ||
export class MyModule {} | ||
``` | ||
## API | ||
**@Input** | ||
#### Inputs | ||
- **`ngModel`** - [**`string[]`**] - Model of the component. Accepts an array of strings as input. | ||
@@ -71,3 +75,3 @@ - **`placeholder`** - [**`?string`**] - String that sets the placeholder of the input for entering new terms. | ||
**@Output** | ||
#### Outputs | ||
- **`onAdd`** - [**`?onAdd(item: string)`**] - event fired when an item has been added | ||
@@ -80,54 +84,177 @@ - **`onRemove`** - [**`?onRemove(item: string)`**] - event fired when an item has been removed | ||
Basic examples: | ||
### Basic Example | ||
#### Component | ||
// example app | ||
```javascript | ||
@Component({ | ||
selector: 'app', | ||
template: `<tag-input [(ngModel)]='items'></tag-input>` | ||
}); | ||
export class App { | ||
items = ['Pizza', 'Pasta', 'Parmesan']; | ||
options = { | ||
placeholder: "+ term", | ||
secondaryPlaceholder: "Enter a new term", | ||
separatorKeys: [4, 5] | ||
maxItems: 10 | ||
} | ||
onItemAdded(item) { | ||
console.log(``${item} has been added`) | ||
} | ||
onItemRemoved(item) { | ||
console.log(``${item} has been removed :(`) | ||
} | ||
// ... | ||
} | ||
``` | ||
@Component({ | ||
selector: 'app', | ||
template: `<tag-input [(ngModel)]='items'></tag-input>` | ||
}); | ||
export class App { | ||
items = ['Pizza', 'Pasta', 'Parmesan']; | ||
options = { | ||
placeholder: "+ term", | ||
secondaryPlaceholder: "Enter a new term", | ||
separatorKeys: [4, 5] | ||
maxItems: 10 | ||
#### Template | ||
```html | ||
<tag-input [(ngModel)]='items' | ||
[placeholder]="options.placeholder" | ||
[secondaryPlaceholder]="options.secondaryPlaceholder" | ||
[maxItems]="options.maxItems" | ||
[separatorKeys]="options.separatorKeys"> | ||
</tag-input> | ||
``` | ||
### More examples | ||
#### Max number of items | ||
```html | ||
<tag-input [(ngModel)]='items' [maxItems]='5'></tag-input> | ||
``` | ||
#### Autocomplete | ||
```html | ||
<tag-input [ngModel]="['@item']" | ||
[autocompleteItems]="['Item1', 'item2', 'item3']" | ||
[autocomplete]="true"> | ||
</tag-input> | ||
``` | ||
This will accept items only from the autocomplete dropdown: | ||
```html | ||
<tag-input [ngModel]="['@item']" | ||
[onlyFromAutocomplete]="true" | ||
[autocompleteItems]="['Item1', 'item2', 'item3']" | ||
[autocomplete]="true"> | ||
</tag-input> | ||
``` | ||
#### Additional keys to separate tags | ||
If you want to use more keys to separate items, add them to separatorKeys as an array of keyboard key codes. | ||
```html | ||
<tag-input [(ngModel)]='items' separatorKeys="[32]"></tag-input> | ||
``` | ||
#### Validation | ||
Create some validation methods in your component: | ||
```javascript | ||
class MyComponent { | ||
private startsWithAt(control: FormControl) { | ||
if (control.value.charAt(0) !== '@') { | ||
return { | ||
'startsWithAt@': true | ||
}; | ||
} | ||
return null; | ||
} | ||
onItemAdded(item) { | ||
console.log(``${item} has been added`) | ||
private endsWith$(control: FormControl) { | ||
if (control.value.charAt(control.value.length - 1) !== '$') { | ||
return { | ||
'endsWith$': true | ||
}; | ||
} | ||
return null; | ||
} | ||
onItemRemoved(item) { | ||
console.log(``${item} has been removed :(`) | ||
} | ||
// ... | ||
public validators = [this.startsWithAt, this.endsWith$]; | ||
public errorMessages = { | ||
'startsWithAt@': 'Your items need to start with "@"', | ||
'endsWith$': 'Your items need to end with "$"' | ||
}; | ||
} | ||
``` | ||
Pass them to the tag-input component: | ||
```html | ||
<tag-input [ngModel]="['@item']" | ||
[errorMessages]="errorMessages" | ||
[validators]="validators"> | ||
</tag-input> | ||
``` | ||
#### Items Transformer | ||
Set up a transformer, which is a function that takes the item's string as parameter, and should return | ||
the transformed string. | ||
```javascript | ||
class MyComponent { | ||
public transformer(item: string): string { | ||
return `@${item}`; | ||
} | ||
// ... | ||
} | ||
``` | ||
// PROPERTIES | ||
<tag-input [(ngModel)]='items' | ||
[placeholder]="options.placeholder" | ||
[secondaryPlaceholder]="options.secondaryPlaceholder" | ||
[maxItems]="options.maxItems" | ||
[separatorKeys]="options.separatorKeys"> | ||
</tag-input> | ||
Every item entered will be prefixed with `@`. | ||
// EVENTS | ||
<tag-input [(ngModel)]='items' | ||
(onRemove)="onItemRemoved($event)" | ||
(onAdd)="onItemAdded($event)"> | ||
</tag-input> | ||
```html | ||
<tag-input [ngModel]="['@item']"[transform]="transformer"></tag-input> | ||
``` | ||
#### Events | ||
Set up some methods that will fire when its relative event is outputted. | ||
// CUSTOM TEMPLATES | ||
// Input tag with a custom template | ||
```html | ||
<tag-input [(ngModel)]='items' | ||
(onBlur)="onInputBlurred($event)" | ||
(onFocus)="onInputFocused($event)" | ||
(onSelect)="onSelected($event)" | ||
(onRemove)="onItemRemoved($event)" | ||
(onAdd)="onItemAdded($event)"> | ||
</tag-input> | ||
``` | ||
<tag-input [(ngModel)]='items' #input> // create a reference #input to the controller in order to use its API | ||
<div class='tag' *ngFor='let item of input.value'> // loop over the items | ||
<div class='tag__name'> {{ item }} </span> // display its values | ||
<span (click)="input.remove(item)"> | ||
Remove me | ||
</span> | ||
</div> | ||
</tag-input> | ||
#### Readonly | ||
If readonly is passed to the tag-input, it won't be possible to select, add and remove items. | ||
If you want to see more advanced examples, please have a look at [http://www.webpackbin.com/VyLKAtssb](http://www.webpackbin.com/VyLKAtssb). | ||
```html | ||
<tag-input [ngModel]="['Javascript', 'Typescript']" [readonly]="true"></tag-input> | ||
``` | ||
#### Custom template | ||
Define your own template, but remember to set up the needed events using the `input` reference. | ||
```html | ||
<tag-input [(ngModel)]='items' #input> // create a reference #input to the controller in order to use its API | ||
<div class='tag' *ngFor='let item of input.value'> // loop over the items | ||
<div class='tag__name'> {{ item }} </span> // display its values | ||
<span (click)="input.remove(item)"> | ||
Remove me | ||
</span> | ||
</div> | ||
</tag-input> | ||
``` | ||
#### New Themes | ||
If you don't like how the default theme looks, or you just need it to | ||
fit in a different design, you can choose 2 new themes: `dark` and `minimal`. | ||
```html | ||
<tag-input [(ngModel)]='items' theme='minimal'></tag-input> | ||
<tag-input [(ngModel)]='items' theme='dark'></tag-input> | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
257
249223
43
2807
Updatedng2-material-dropdown@^0.3.6