Skip to content

Commit

Permalink
feat(module: searchbar): searchbar add ngModel (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
nuonuoge authored and fisherspy committed Dec 25, 2018
1 parent 9359604 commit 8bd39d7
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 4 deletions.
2 changes: 1 addition & 1 deletion components/search-bar/demo/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { Component, ElementRef, Renderer } from '@angular/core';
<div class="sub-title">Show cancel button</div>
</div>
<div style="border-bottom: 1px solid #ddd;">
<SearchBar [value]="value"
<SearchBar [(ngModel)]="value"
[placeholder]="'Search'"
[showCancelButton]="true"
(onBlur)="blur()"
Expand Down
2 changes: 2 additions & 0 deletions components/search-bar/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Normally located below NavBar, the activation status is exited by the Cancel but

Properties | Descrition | Type | Default
-----------|------------|------|--------
| ngModel | the controlled current value, dobule binding | String | <span> </span> |
| ngModelChange | event callback | (val: string): void | <span> </span> |
| defaultValue | the uncontrolled default value | String | <span> </span> |
| value | the controlled current value | String | <span> </span> |
| placeholder | placeholder | String | <span> </span> |
Expand Down
2 changes: 2 additions & 0 deletions components/search-bar/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ subtitle: 搜索栏

属性 | 说明 | 类型 | 默认值
----|-----|------|------
| ngModel | 当前值,可双向绑定 | String|<span> </span> |
| ngModelChange | 值改变时回调 | (val: string): void |<span> </span> |
| defaultValue | 搜索框的默认值 | String | <span> </span> |
| value | 搜索框的当前值 | String | <span> </span> |
| placeholder | placeholder | String | <span> </span> |
Expand Down
33 changes: 32 additions & 1 deletion components/search-bar/search-bar.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { SearchBarModule } from './search-bar.module';
Expand All @@ -9,21 +10,23 @@ describe('SearchBarComponent', () => {
let component: TestSearchBarComponent;
let fixture: ComponentFixture<TestSearchBarComponent>;
let searchBarEle;
let searchBarEles;
let inputEle;
let formEle;
let buttonEle;
let cancelEle;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestSearchBarComponent],
imports: [SearchBarModule, BrowserAnimationsModule, LocaleProviderModule]
imports: [SearchBarModule, BrowserAnimationsModule, LocaleProviderModule, FormsModule]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(TestSearchBarComponent);
component = fixture.componentInstance;
searchBarEle = fixture.debugElement.query(By.css('SearchBar'));
searchBarEles = fixture.debugElement.queryAll(By.css('SearchBar'));
inputEle = searchBarEle.nativeElement.querySelector('input');
formEle = searchBarEle.nativeElement.querySelector('form');
buttonEle = fixture.debugElement.query(By.css('.am-button')).nativeElement;
Expand Down Expand Up @@ -112,6 +115,25 @@ describe('SearchBarComponent', () => {
clearEle.click();
expect(component.change).toHaveBeenCalledTimes(1);
});

it('should ngModel work', fakeAsync(() => {
const inputEleNext = searchBarEles[1].nativeElement.querySelector('input');
component.modelValue = 'test';
fixture.detectChanges();
tick();
expect(inputEleNext.value).toBe('test', 'value is test');

component.modelValue = null;
fixture.detectChanges();
tick();
expect(inputEleNext.value).toBe('', 'value is undefined');
}));

it('should ngModelChange work', () => {
const clearEle = searchBarEles[1].nativeElement.querySelector('a');
clearEle.click();
expect(component.modelChange).toHaveBeenCalledTimes(1);
});
});

@Component({
Expand All @@ -132,12 +154,20 @@ describe('SearchBarComponent', () => {
(onCancel)="cancel()"
(onChange)="change($event)"
></SearchBar>
<SearchBar [ngModel]="modelValue"
[maxLength]="maxLength"
[cancelText]="cancelText"
[placeholder]="placeholder"
[showCancelButton]="showCancelButton"
(ngModelChange)="modelChange($event)"
></SearchBar>
<a role="button" class="am-button" (click)="handleClick()"><span>click to focus</span></a>
`
})
export class TestSearchBarComponent {
defaultValue = '';
value = '';
modelValue = '';
placeholder = '';
showCancelButton = false;
cancelText = '取消';
Expand All @@ -153,6 +183,7 @@ export class TestSearchBarComponent {
focus = jasmine.createSpy('focus callback');
blur = jasmine.createSpy('blur callback');
change = jasmine.createSpy('change callback');
modelChange = jasmine.createSpy('ngModelChange callback');

constructor() {}

Expand Down
21 changes: 19 additions & 2 deletions components/search-bar/search-bar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { trigger, state, animate, transition, style } from '@angular/animations'
import { LocaleProviderService } from '../locale-provider/locale-provider.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

@Component({
selector: 'SearchBar, nzm-search-bar',
Expand All @@ -38,7 +38,7 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
])
]
})
export class SearchBar implements OnInit, AfterViewInit, AfterViewChecked, OnDestroy {
export class SearchBar implements OnInit, AfterViewInit, AfterViewChecked, OnDestroy, ControlValueAccessor {
prefixCls: string = 'am-search';
clearCls: object;
wrapCls: object;
Expand Down Expand Up @@ -149,6 +149,8 @@ export class SearchBar implements OnInit, AfterViewInit, AfterViewChecked, OnDes
onCancel = new EventEmitter<any>();
@Output()
onClear = new EventEmitter<any>();
private onChangeFn: (value: string) => void = () => {};
private onTouchFn: (value: string) => void = () => {};

constructor(private _elementRef: ElementRef, private _localeProvider: LocaleProviderService) {}

Expand Down Expand Up @@ -210,6 +212,7 @@ export class SearchBar implements OnInit, AfterViewInit, AfterViewChecked, OnDes
onSearchbarChange(e) {
this._focus = true;
this.onChange.emit(e);
this.onChangeFn(e);
this.setClass();
}

Expand Down Expand Up @@ -245,6 +248,20 @@ export class SearchBar implements OnInit, AfterViewInit, AfterViewChecked, OnDes
this.onSearchbarFocus();
}

writeValue(value: any): void {
this._value = value || '';
this.inputElementRef.nativeElement.value = this._value;
this.setClass();
}

registerOnChange(fn: (value: string) => void): void {
this.onChangeFn = fn;
}

registerOnTouched(fn: (value: string) => void): void {
this.onTouchFn = fn;
}

ngOnInit() {
this.setClass();
this._localeProvider.localeChange.pipe(takeUntil(this._unsubscribe$)).subscribe(_ => {
Expand Down

0 comments on commit 8bd39d7

Please sign in to comment.