diff --git a/README.md b/README.md index 1cfe66c7..8a127219 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Native Angular component for Select 4. Add the tag `` into some html ```html - + ``` 5. More information regarding of using **ngx-select-ex** is located in [demo](https://optimistex.github.io/ngx-select-ex/). @@ -83,6 +83,27 @@ Any item can be `disabled` for prevent selection. For disable an item add the pr | (blur) | Fired on select blur | | (open) | Fired on select dropdown open | | (close) | Fired on select dropdown close | +| (select) | Fired on an item selected by user. Returns value of the selected item. | +| (remove) | Fired on an item removed by user. Returns value of the removed item. | + +**Warning!** Although the component contains the `select` and the `remove` events, the better solution is using `valueChanches` of the `FormControl`. + +```typescript +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; + +@Component({ + selector: 'app-example', + template: `` +}) +class ExampleComponent { + public selectControl = new FormControl(); + + constructor() { + this.selectControl.valueChanges.subscribe(value => console.log(value)); + } +} +``` ### Styles and customization diff --git a/src/app/demo/select/single-demo.html b/src/app/demo/select/single-demo.html index 91ba0035..2468a953 100644 --- a/src/app/demo/select/single-demo.html +++ b/src/app/demo/select/single-demo.html @@ -10,7 +10,9 @@

Select a single city

(focus)="doFocus()" (blur)="doBlur()" (open)="doOpen()" - (close)="doClose()"> + (close)="doClose()" + (select)="doSelect($event)" + (remove)="doRemove($event)">

diff --git a/src/app/demo/select/single-demo.ts b/src/app/demo/select/single-demo.ts index 2eeff9b0..8610f768 100644 --- a/src/app/demo/select/single-demo.ts +++ b/src/app/demo/select/single-demo.ts @@ -61,4 +61,12 @@ export class SingleDemoComponent implements OnDestroy { public doClose() { console.log('SingleDemoComponent.doClose'); } + + public doSelect(value: any) { + console.log('SingleDemoComponent.doSelect', value); + } + + public doRemove(value: any) { + console.log('SingleDemoComponent.doRemove', value); + } } diff --git a/src/app/doc.md b/src/app/doc.md index 33a6a9b0..56e004c5 100644 --- a/src/app/doc.md +++ b/src/app/doc.md @@ -69,6 +69,27 @@ Any item can be `disabled` for prevent selection. For disable an item add the pr | (blur) | Fired on select blur | | (open) | Fired on select dropdown open | | (close) | Fired on select dropdown close | +| (select) | Fired on an item selected by user. Returns value of the selected item. | +| (remove) | Fired on an item removed by user. Returns value of the removed item. | + +**Warning!** Although the component contains the `select` and the `remove` events, the better solution is using `valueChanches` of the `FormControl`. + +```typescript +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; + +@Component({ + selector: 'app-example', + template: `` +}) +class ExampleComponent { + public selectControl = new FormControl(); + + constructor() { + this.selectControl.valueChanges.subscribe(value => console.log(value)); + } +} +``` ### Styles and customization diff --git a/src/app/lib/ngx-select/ngx-select.component.spec.ts b/src/app/lib/ngx-select/ngx-select.component.spec.ts index 67af09ae..4a5d75f0 100644 --- a/src/app/lib/ngx-select/ngx-select.component.spec.ts +++ b/src/app/lib/ngx-select/ngx-select.component.spec.ts @@ -27,7 +27,9 @@ import createSpy = jasmine.createSpy; (focus)="select1.doFocus()" (blur)="select1.doBlur()" (open)="select1.doOpen()" - (close)="select1.doClose()"> + (close)="select1.doClose()" + (select)="select1.doSelect($event)" + (remove)="select1.doRemove($event)"> + [items]="select2.items" + (select)="select2.doSelect($event)" + (remove)="select2.doRemove($event)"> ` }) class TestNgxSelectComponent { @@ -65,7 +69,9 @@ class TestNgxSelectComponent { doFocus: () => null, doBlur: () => null, doOpen: () => null, - doClose: () => null + doClose: () => null, + doSelect: () => null, + doRemove: () => null }; public select2: any = { @@ -80,7 +86,10 @@ class TestNgxSelectComponent { optGroupOptionsField: 'options', multiple: false, noAutoComplete: false, - items: [] + items: [], + + doSelect: () => null, + doRemove: () => null }; } @@ -551,8 +560,12 @@ describe('NgxSelectComponent', () => { }); describe('should remove selected', () => { + let doSelect, doRemove; + describe('from select with ngModel', () => { beforeEach(() => { + doSelect = spyOn(fixture.componentInstance.select1, 'doSelect'); + doRemove = spyOn(fixture.componentInstance.select1, 'doRemove'); fixture.componentInstance.select1.items = items1; fixture.componentInstance.select1.allowClear = true; fixture.detectChanges(); @@ -565,7 +578,7 @@ describe('NgxSelectComponent', () => { }); it('a single item', () => { - el(1).querySelector('.btn-link').click(); + el(1).querySelector('.ngx-select__clear').click(); fixture.detectChanges(); expect(selectedItem(1)).toBeFalsy(); expect(fixture.componentInstance.select1.value).toEqual(null); @@ -579,10 +592,19 @@ describe('NgxSelectComponent', () => { expect(selectedItems(1).length).toBe(0); expect(fixture.componentInstance.select1.value).toEqual([]); }); + + afterEach(() => { + expect(doSelect).toHaveBeenCalledTimes(1); + expect(doSelect).toHaveBeenCalledWith(0); + expect(doRemove).toHaveBeenCalledTimes(1); + expect(doRemove).toHaveBeenCalledWith(0); + }); }); describe('from select with FormControl', () => { beforeEach(() => { + doSelect = spyOn(fixture.componentInstance.select2, 'doSelect'); + doRemove = spyOn(fixture.componentInstance.select2, 'doRemove'); fixture.componentInstance.select2.items = items1; fixture.componentInstance.select2.allowClear = true; fixture.detectChanges(); @@ -595,7 +617,7 @@ describe('NgxSelectComponent', () => { }); it('a single item', () => { - el(2).querySelector('.btn-link').click(); + el(2).querySelector('.ngx-select__clear').click(); fixture.detectChanges(); expect(selectedItem(2)).toBeFalsy(); expect(fixture.componentInstance.select2.formControl.value).toEqual(null); @@ -609,6 +631,13 @@ describe('NgxSelectComponent', () => { expect(selectedItems(2).length).toBe(0); expect(fixture.componentInstance.select2.formControl.value).toEqual([]); }); + + afterEach(() => { + expect(doSelect).toHaveBeenCalledTimes(1); + expect(doSelect).toHaveBeenCalledWith(0); + expect(doRemove).toHaveBeenCalledTimes(1); + expect(doRemove).toHaveBeenCalledWith(0); + }); }); }); diff --git a/src/app/lib/ngx-select/ngx-select.component.ts b/src/app/lib/ngx-select/ngx-select.component.ts index c8178dc7..0da6aa52 100644 --- a/src/app/lib/ngx-select/ngx-select.component.ts +++ b/src/app/lib/ngx-select/ngx-select.component.ts @@ -65,6 +65,8 @@ export class NgxSelectComponent implements ControlValueAccessor, DoCheck, AfterC @Output() public blur = new EventEmitter(); @Output() public open = new EventEmitter(); @Output() public close = new EventEmitter(); + @Output() public select = new EventEmitter(); + @Output() public remove = new EventEmitter(); @ViewChild('main') protected mainElRef: ElementRef; @ViewChild('input') protected inputElRef: ElementRef; @@ -336,6 +338,7 @@ export class NgxSelectComponent implements ControlValueAccessor, DoCheck, AfterC } if (!option.disabled) { this.subjOptionsSelected.next((this.multiple ? this.subjOptionsSelected.value : []).concat([option])); + this.select.emit(option.value); this.optionsClose(true); this.onTouched(); } @@ -345,6 +348,7 @@ export class NgxSelectComponent implements ControlValueAccessor, DoCheck, AfterC if (!this.disabled) { event.stopPropagation(); this.subjOptionsSelected.next((this.multiple ? this.subjOptionsSelected.value : []).filter(o => o !== option)); + this.remove.emit(option.value); } }