From 20585106ffa7d4f0d313fa52ad6464727b8199a1 Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Fri, 18 Dec 2015 16:41:52 -0500 Subject: [PATCH 1/6] refactor(searchbar): WIP Angularizing searchbar --- ionic/components/searchbar/searchbar.ts | 204 +++++++++--------- .../searchbar/test/floating/index.ts | 10 +- .../searchbar/test/floating/main.html | 9 +- 3 files changed, 101 insertions(+), 122 deletions(-) diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index bd7215803c..88dd159e66 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -1,12 +1,74 @@ -import {ElementRef, Renderer, Directive, Host, forwardRef, ViewChild, Output, EventEmitter} from 'angular2/core'; +import {ElementRef, Renderer, Component, Directive} from 'angular2/core'; +import {Host, HostBinding, HostListener, ViewChild, Input, Output, EventEmitter, Optional} from 'angular2/core'; import {NgIf, NgClass, NgControl, FORM_DIRECTIVES} from 'angular2/common'; import {Ion} from '../ion'; import {Config} from '../../config/config'; -import {ConfigComponent} from '../../decorators/config-component'; import {Icon} from '../icon/icon'; import {Button} from '../button/button'; + +/** +* @private +*/ +@Directive({ + selector: '.searchbar-input', +}) +export class SearchbarInput { + @HostListener('keyup', ['$event']) + /** + * @private + * Update the Searchbar input value when the input changes + */ + private inputChanged(ev) { + this.writeValue(ev.target.value); + this.onChange(ev.target.value); + } + + constructor( + @Optional ngControl: NgControl, + elementRef: ElementRef, + renderer: Renderer + ) { + this.renderer = renderer; + this.elementRef = elementRef; + + if (!ngControl) return; + + this.ngControl = ngControl; + this.ngControl.valueAccessor = this; + } + + /** + * @private + * Write a new value to the element. + */ + public writeValue(value: any) { + this.value = value; + } + + public onChange = (_:any) => {}; + public onTouched = () => {}; + + /** + * @private + * Set the function to be called when the control receives a change event. + */ + public registerOnChange(fn:(_:any) => {}):void { + this.onChange = fn; + } + + /** + * @private + * Set the function to be called when the control receives a touch event. + */ + public registerOnTouched(fn:() => {}):void { + this.onTouched = fn; + } + +} + + /** * @name Searchbar * @module ionic @@ -15,29 +77,20 @@ import {Button} from '../button/button'; * * @usage * ```html - * + * * ``` * - * @property {function} [cancelButtonAction] - the function that gets called by clicking the cancel button - * @property {string} [cancelButtonText=Cancel] - sets the cancel button text to the value passed in + * @property {string} [cancelButtonText=Cancel] - Sets the cancel button text to the value passed in * @property {boolean} [hideCancelButton=false] - Hides the cancel button * @property {string} [placeholder=Search] - Sets input placeholder to the value passed in * + * @property {Any} [input] - Expression to evaluate when the Searchbar input has changed + * @property {Any} [cancel] - Expression to evaluate when the cancel button is clicked. + * * @see {@link /docs/v2/components#search Search Component Docs} */ -@ConfigComponent({ +@Component({ selector: 'ion-searchbar', - inputs: [ - 'cancelButtonAction', - 'cancelButtonText', - 'hideCancelButton', - 'placeholder' - ], - outputs: ['input'], - host: { - '[class.searchbar-left-aligned]': 'shouldLeftAlign', - '[class.searchbar-focused]': 'isFocused', - }, template: '
' + '' + '
' + '', - directives: [FORM_DIRECTIVES, NgIf, NgClass, Icon, Button, forwardRef(() => SearchbarInput)] + directives: [FORM_DIRECTIVES, NgIf, NgClass, Icon, Button, SearchbarInput] }) export class Searchbar extends Ion { - @ViewChild(forwardRef(() => SearchbarInput)) searchbarInput; - query: string; + @Input cancelButtonText: string; + @Input hideCancelButton: any; + @Input placeholder: string; + + // @Output input: EventEmitter = new EventEmitter(); + @Output cancel: EventEmitter = new EventEmitter(); + + @HostBinding('class.searchbar-focused') isFocused; + + @HostBinding('class.searchbar-left-aligned') + /** + * @private + * Check if the Searchbar has a value and left align if so + */ + private shouldLeftAlign() { + return this.searchbarInput && this.searchbarInput.value && this.searchbarInput.value.trim() != ''; + } + + @ViewChild(SearchbarInput) searchbarInput; + + query: string = ''; blurInput = true; constructor( @@ -65,15 +137,11 @@ export class Searchbar extends Ion { this.renderer = renderer; this.elementRef = elementRef; - this.input = new EventEmitter('input'); - // If there is no control then we shouldn't do anything if (!ngControl) return; this.ngControl = ngControl; this.ngControl.valueAccessor = this; - - this.query = ''; } /** @@ -90,21 +158,12 @@ export class Searchbar extends Ion { this.placeholder = this.placeholder || 'Search'; } - /** - * @private - * After the view has initialized check if the Searchbar has a value - */ - ngAfterViewInit() { - this.shouldLeftAlign = this.searchbarInput.value && this.searchbarInput.value.trim() != ''; - } - /** * @private * Sets the Searchbar to focused and aligned left on input focus. */ inputFocused() { this.isFocused = true; - this.shouldLeftAlign = true; } /** @@ -120,9 +179,7 @@ export class Searchbar extends Ion { this.blurInput = true; return; } - //console.log("Blurring input"); this.isFocused = false; - this.shouldLeftAlign = this.searchbarInput.value && this.searchbarInput.value.trim() != ''; } /** @@ -130,7 +187,6 @@ export class Searchbar extends Ion { * Clears the input field and triggers the control change. */ clearInput() { - //console.log("Clearing input"); this.searchbarInput.writeValue(''); this.searchbarInput.onChange(''); this.blurInput = false; @@ -142,12 +198,11 @@ export class Searchbar extends Ion { * the clearInput function doesn't want the input to blur * then calls the custom cancel function if the user passed one in. */ - cancelSearchbar(event, value) { - //console.log("Cancel searchbar"); + cancelSearchbar(ev, value) { this.clearInput(); this.blurInput = true; - - this.cancelButtonAction && this.cancelButtonAction(event, value); + console.log("should cancel"); + this.cancel.next(); } /** @@ -156,73 +211,6 @@ export class Searchbar extends Ion { */ updateQuery(value) { this.query = value; - this.input.next(value); + this.input.emit(); } } - -/** -* @private -* Updates the value of query -*/ -@Directive({ - selector: '.searchbar-input', - host: { - '(keyup)': 'inputChanged($event)' - } -}) -export class SearchbarInput { - constructor( - @Host() searchbar: Searchbar, - elementRef: ElementRef, - renderer: Renderer - ) { - this.searchbar = searchbar; - this.renderer = renderer; - this.elementRef = elementRef; - - if (!searchbar.ngControl) return; - - this.onChange = (_) => {}; - this.onTouched = (_) => {}; - - this.ngControl = searchbar.ngControl; - this.ngControl.valueAccessor = this; - } - - /** - * @private - * Write a new value to the element. - */ - writeValue(value) { - this.value = value; - if (typeof value === 'string') { - this.searchbar.updateQuery(value); - } - } - - /** - * @private - * Set the function to be called when the control receives a change event. - */ - registerOnChange(fn) { - this.onChange = fn; - } - - /** - * @private - * Set the function to be called when the control receives a touch event. - */ - registerOnTouched(fn) { - this.onTouched = fn; - } - - /** - * @private - * Update the Searchbar input value when the input changes - */ - inputChanged(event) { - this.writeValue(event.target.value); - this.onChange(event.target.value); - } - -} diff --git a/ionic/components/searchbar/test/floating/index.ts b/ionic/components/searchbar/test/floating/index.ts index a9421e79e2..342d36b12b 100644 --- a/ionic/components/searchbar/test/floating/index.ts +++ b/ionic/components/searchbar/test/floating/index.ts @@ -8,27 +8,25 @@ import {SearchPipe} from 'ionic/components/searchbar/searchbar'; directives: [FORM_DIRECTIVES] }) class E2EApp { - defaultSearch: string = ''; + defaultSearch: string = 'test'; customPlaceholder: string = ''; defaultCancel: string = ''; customCancel: string = ''; customCancelAction: string = ''; - clickedCustomAction: boolean = false; constructor() { } - myCancelAction(event, query) { - console.log("Clicked cancel action with", query); - this.clickedCustomAction = true; + onCancelSearchbar(ev) { + console.log("Clicked cancel action with", ev); } triggerInput(ev) { // The defaultSearch doesn't get updated before this function is called // so we have to wrap it in a timeout setTimeout(() => { - console.log("Triggered input", this.defaultSearch); + console.log("Triggered input", ev); }); } } diff --git a/ionic/components/searchbar/test/floating/main.html b/ionic/components/searchbar/test/floating/main.html index 27eecacf83..318bcb9fab 100644 --- a/ionic/components/searchbar/test/floating/main.html +++ b/ionic/components/searchbar/test/floating/main.html @@ -1,6 +1,6 @@
Search - Default
- +

Default Search: {{ defaultSearch }} @@ -14,11 +14,4 @@

Search - Custom Cancel Button Danger
- -
Search - Custom Cancel Action
- - -
- Clicked custom action with input = {{customCancelAction}} -
From 53dd312b39c508a4c893d3c78d5e082ed12db168 Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Fri, 18 Dec 2015 18:04:15 -0500 Subject: [PATCH 2/6] refactor(searchbar): fixing event emitters, outputs and inputs, removing ngControl requirement from Searchbar --- ionic/components/searchbar/searchbar.ts | 75 +++++++------------ .../searchbar/test/floating/index.ts | 16 ++-- .../searchbar/test/floating/main.html | 8 +- ionic/components/text-input/text-input.ts | 2 - 4 files changed, 39 insertions(+), 62 deletions(-) diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index 88dd159e66..29e300027f 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -1,5 +1,4 @@ -import {ElementRef, Renderer, Component, Directive} from 'angular2/core'; -import {Host, HostBinding, HostListener, ViewChild, Input, Output, EventEmitter, Optional} from 'angular2/core'; +import {ElementRef, Component, Directive, Host, HostBinding, HostListener, ViewChild, Input, Output, EventEmitter} from 'angular2/core'; import {NgIf, NgClass, NgControl, FORM_DIRECTIVES} from 'angular2/common'; import {Ion} from '../ion'; @@ -25,14 +24,7 @@ export class SearchbarInput { this.onChange(ev.target.value); } - constructor( - @Optional ngControl: NgControl, - elementRef: ElementRef, - renderer: Renderer - ) { - this.renderer = renderer; - this.elementRef = elementRef; - + constructor(ngControl: NgControl) { if (!ngControl) return; this.ngControl = ngControl; @@ -77,7 +69,7 @@ export class SearchbarInput { * * @usage * ```html - * + * * ``` * * @property {string} [cancelButtonText=Cancel] - Sets the cancel button text to the value passed in @@ -86,6 +78,7 @@ export class SearchbarInput { * * @property {Any} [input] - Expression to evaluate when the Searchbar input has changed * @property {Any} [cancel] - Expression to evaluate when the cancel button is clicked. + * @property {Any} [clear] - Expression to evaluate when the clear input button is clicked. * * @see {@link /docs/v2/components#search Search Component Docs} */ @@ -93,23 +86,27 @@ export class SearchbarInput { selector: 'ion-searchbar', template: '
' + - '' + '
' + - '' + + '' + '' + '
' + - '', + '', directives: [FORM_DIRECTIVES, NgIf, NgClass, Icon, Button, SearchbarInput] }) export class Searchbar extends Ion { - @Input cancelButtonText: string; - @Input hideCancelButton: any; - @Input placeholder: string; + @ViewChild(SearchbarInput) searchbarInput; - // @Output input: EventEmitter = new EventEmitter(); - @Output cancel: EventEmitter = new EventEmitter(); + @Input() cancelButtonText: string; + @Input() hideCancelButton: any; + @Input() placeholder: string; + @Input() ngModel: any; + + @Output() input: EventEmitter = new EventEmitter(); + @Output() cancel: EventEmitter = new EventEmitter(); + @Output() clear: EventEmitter = new EventEmitter(); @HostBinding('class.searchbar-focused') isFocused; @@ -118,30 +115,19 @@ export class Searchbar extends Ion { * @private * Check if the Searchbar has a value and left align if so */ - private shouldLeftAlign() { - return this.searchbarInput && this.searchbarInput.value && this.searchbarInput.value.trim() != ''; - } + private get shouldLeftAlign() { + return this.value && this.value.trim() != ''; + }; - @ViewChild(SearchbarInput) searchbarInput; - - query: string = ''; + value: string = ''; blurInput = true; constructor( elementRef: ElementRef, config: Config, - ngControl: NgControl, - renderer: Renderer ) { super(elementRef, config); - this.renderer = renderer; this.elementRef = elementRef; - - // If there is no control then we shouldn't do anything - if (!ngControl) return; - - this.ngControl = ngControl; - this.ngControl.valueAccessor = this; } /** @@ -156,6 +142,9 @@ export class Searchbar extends Ion { this.cancelButtonText = this.cancelButtonText || 'Cancel'; this.placeholder = this.placeholder || 'Search'; + + if (this.ngModel) this.value = this.ngModel; + console.log(this.value); } /** @@ -187,9 +176,9 @@ export class Searchbar extends Ion { * Clears the input field and triggers the control change. */ clearInput() { - this.searchbarInput.writeValue(''); - this.searchbarInput.onChange(''); + this.value = ''; this.blurInput = false; + this.clear.emit(this); } /** @@ -198,19 +187,9 @@ export class Searchbar extends Ion { * the clearInput function doesn't want the input to blur * then calls the custom cancel function if the user passed one in. */ - cancelSearchbar(ev, value) { + cancelSearchbar() { this.clearInput(); this.blurInput = true; - console.log("should cancel"); - this.cancel.next(); + this.cancel.emit(this); } - - /** - * @private - * Updates the value of query - */ - updateQuery(value) { - this.query = value; - this.input.emit(); - } } diff --git a/ionic/components/searchbar/test/floating/index.ts b/ionic/components/searchbar/test/floating/index.ts index 342d36b12b..f106043615 100644 --- a/ionic/components/searchbar/test/floating/index.ts +++ b/ionic/components/searchbar/test/floating/index.ts @@ -18,15 +18,15 @@ class E2EApp { } - onCancelSearchbar(ev) { - console.log("Clicked cancel action with", ev); + onClearSearchbar(searchbar) { + // console.log("Clicked clear input on", searchbar.value); } - triggerInput(ev) { - // The defaultSearch doesn't get updated before this function is called - // so we have to wrap it in a timeout - setTimeout(() => { - console.log("Triggered input", ev); - }); + onCancelSearchbar(searchbar) { + console.log("Clicked cancel button with", searchbar.value); + } + + triggerInput(searchbar) { + // console.log("Triggered input", searchbar.value); } } diff --git a/ionic/components/searchbar/test/floating/main.html b/ionic/components/searchbar/test/floating/main.html index 318bcb9fab..3d135a58a2 100644 --- a/ionic/components/searchbar/test/floating/main.html +++ b/ionic/components/searchbar/test/floating/main.html @@ -1,17 +1,17 @@
Search - Default
- +

Default Search: {{ defaultSearch }}

Search - Custom Placeholder
- +
Search - Hide Cancel Button
- +
Search - Custom Cancel Button Danger
- +
diff --git a/ionic/components/text-input/text-input.ts b/ionic/components/text-input/text-input.ts index f64ffb1218..78cc86fc9f 100644 --- a/ionic/components/text-input/text-input.ts +++ b/ionic/components/text-input/text-input.ts @@ -489,10 +489,8 @@ export class TextInputElement { } ngOnInit() { - if (this.ngModel) console.log("Value", this.ngModel); if (this.ngModel) this.value = this.ngModel; this.wrapper && this.wrapper.hasValue(this.value); - console.log(this.value); } focusChange(changed) { From df035003f7518e8b45c012c5013c8cfb66b903ed Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Fri, 18 Dec 2015 19:08:58 -0500 Subject: [PATCH 3/6] fix(searchbar): fix left align and add elementRef back to input component --- ionic/components/searchbar/searchbar.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index 29e300027f..6c2d33b477 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -24,7 +24,9 @@ export class SearchbarInput { this.onChange(ev.target.value); } - constructor(ngControl: NgControl) { + constructor(ngControl: NgControl, elementRef: ElementRef) { + this.elementRef = elementRef; + if (!ngControl) return; this.ngControl = ngControl; @@ -90,8 +92,8 @@ export class SearchbarInput { '' + '' + '
' + - '' + - '' + + '' + + '' + '' + '', directives: [FORM_DIRECTIVES, NgIf, NgClass, Icon, Button, SearchbarInput] @@ -110,14 +112,7 @@ export class Searchbar extends Ion { @HostBinding('class.searchbar-focused') isFocused; - @HostBinding('class.searchbar-left-aligned') - /** - * @private - * Check if the Searchbar has a value and left align if so - */ - private get shouldLeftAlign() { - return this.value && this.value.trim() != ''; - }; + @HostBinding('class.searchbar-left-aligned') shouldLeftAlign; value: string = ''; blurInput = true; @@ -127,7 +122,6 @@ export class Searchbar extends Ion { config: Config, ) { super(elementRef, config); - this.elementRef = elementRef; } /** @@ -144,7 +138,7 @@ export class Searchbar extends Ion { this.placeholder = this.placeholder || 'Search'; if (this.ngModel) this.value = this.ngModel; - console.log(this.value); + this.shouldLeftAlign = this.value && this.value.trim() != ''; } /** @@ -153,6 +147,7 @@ export class Searchbar extends Ion { */ inputFocused() { this.isFocused = true; + this.shouldLeftAlign = true; } /** @@ -164,11 +159,13 @@ export class Searchbar extends Ion { // blurInput determines if it should blur // if we are clearing the input we still want to stay focused in the input if (this.blurInput == false) { + console.log(this.searchbarInput); this.searchbarInput.elementRef.nativeElement.focus(); this.blurInput = true; return; } this.isFocused = false; + this.shouldLeftAlign = this.value && this.value.trim() != ''; } /** From c40d71ae1942a01a6900864bba481da3b91dca66 Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Fri, 18 Dec 2015 19:20:01 -0500 Subject: [PATCH 4/6] refactor(searchbar): moving logic out of directive and back into searchbar --- ionic/components/searchbar/searchbar.ts | 92 ++++++++++--------- .../searchbar/test/floating/index.ts | 6 +- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index 6c2d33b477..d8de4e94e7 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -14,52 +14,18 @@ import {Button} from '../button/button'; selector: '.searchbar-input', }) export class SearchbarInput { - @HostListener('keyup', ['$event']) + @HostListener('input', ['$event']) /** * @private * Update the Searchbar input value when the input changes */ private inputChanged(ev) { - this.writeValue(ev.target.value); - this.onChange(ev.target.value); + ev.preventDefault(); } - constructor(ngControl: NgControl, elementRef: ElementRef) { + constructor(elementRef: ElementRef) { this.elementRef = elementRef; - - if (!ngControl) return; - - this.ngControl = ngControl; - this.ngControl.valueAccessor = this; } - - /** - * @private - * Write a new value to the element. - */ - public writeValue(value: any) { - this.value = value; - } - - public onChange = (_:any) => {}; - public onTouched = () => {}; - - /** - * @private - * Set the function to be called when the control receives a change event. - */ - public registerOnChange(fn:(_:any) => {}):void { - this.onChange = fn; - } - - /** - * @private - * Set the function to be called when the control receives a touch event. - */ - public registerOnTouched(fn:() => {}):void { - this.onTouched = fn; - } - } @@ -92,7 +58,7 @@ export class SearchbarInput { '' + '' + '
' + - '' + + '' + '' + '' + '', @@ -110,18 +76,62 @@ export class Searchbar extends Ion { @Output() cancel: EventEmitter = new EventEmitter(); @Output() clear: EventEmitter = new EventEmitter(); + value: string = ''; + blurInput = true; + @HostBinding('class.searchbar-focused') isFocused; @HostBinding('class.searchbar-left-aligned') shouldLeftAlign; - value: string = ''; - blurInput = true; + @HostListener('keyup', ['$event']) + /** + * @private + * Update the Searchbar input value when the input changes + */ + private inputChanged(ev) { + this.value = ev.target.value; + this.onChange(this.value); + this.input.emit(this.value); + } constructor( elementRef: ElementRef, config: Config, + ngControl: NgControl ) { super(elementRef, config); + + if (ngControl) { + this.ngControl = ngControl; + this.ngControl.valueAccessor = this; + } + } + + /** + * @private + * Write a new value to the element. + */ + public writeValue(value: any) { + this.value = value; + } + + public onChange = (_:any) => {}; + public onTouched = () => {}; + + /** + * @private + * Set the function to be called when the control receives a change event. + */ + public registerOnChange(fn:(_:any) => {}):void { + this.onChange = fn; + } + + /** + * @private + * Set the function to be called when the control receives a touch event. + */ + public registerOnTouched(fn:() => {}):void { + this.onTouched = fn; } /** @@ -159,7 +169,6 @@ export class Searchbar extends Ion { // blurInput determines if it should blur // if we are clearing the input we still want to stay focused in the input if (this.blurInput == false) { - console.log(this.searchbarInput); this.searchbarInput.elementRef.nativeElement.focus(); this.blurInput = true; return; @@ -174,6 +183,7 @@ export class Searchbar extends Ion { */ clearInput() { this.value = ''; + this.onChange(this.value); this.blurInput = false; this.clear.emit(this); } diff --git a/ionic/components/searchbar/test/floating/index.ts b/ionic/components/searchbar/test/floating/index.ts index f106043615..f02e06b17a 100644 --- a/ionic/components/searchbar/test/floating/index.ts +++ b/ionic/components/searchbar/test/floating/index.ts @@ -19,14 +19,14 @@ class E2EApp { } onClearSearchbar(searchbar) { - // console.log("Clicked clear input on", searchbar.value); + console.log("Clicked clear input on", searchbar); } onCancelSearchbar(searchbar) { - console.log("Clicked cancel button with", searchbar.value); + console.log("Clicked cancel button with", searchbar); } triggerInput(searchbar) { - // console.log("Triggered input", searchbar.value); + console.log("Triggered input", searchbar); } } From ad4d160af9309ebb7cb3d6fd64fda70734ed9044 Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Fri, 18 Dec 2015 19:32:25 -0500 Subject: [PATCH 5/6] refactor(searchbar): stop the input events and only use the searchbars input event --- ionic/components/searchbar/searchbar.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index d8de4e94e7..b21738b375 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -17,10 +17,11 @@ export class SearchbarInput { @HostListener('input', ['$event']) /** * @private - * Update the Searchbar input value when the input changes + * Don't send the input's input event */ - private inputChanged(ev) { - ev.preventDefault(); + private stopInput(ev) { + event.preventDefault(); + event.stopPropagation(); } constructor(elementRef: ElementRef) { @@ -91,7 +92,7 @@ export class Searchbar extends Ion { private inputChanged(ev) { this.value = ev.target.value; this.onChange(this.value); - this.input.emit(this.value); + this.input.emit(this); } constructor( @@ -182,10 +183,11 @@ export class Searchbar extends Ion { * Clears the input field and triggers the control change. */ clearInput() { + this.clear.emit(this); + this.value = ''; this.onChange(this.value); this.blurInput = false; - this.clear.emit(this); } /** @@ -195,8 +197,9 @@ export class Searchbar extends Ion { * then calls the custom cancel function if the user passed one in. */ cancelSearchbar() { + this.cancel.emit(this); + this.clearInput(); this.blurInput = true; - this.cancel.emit(this); } } From b00b7bca6a72949d7d4a1ce6b1d7251004ccf74b Mon Sep 17 00:00:00 2001 From: Brandy Carney Date: Sat, 19 Dec 2015 14:04:28 -0500 Subject: [PATCH 6/6] refactor(searchbar): fixed searchbar when undefined value is passed or no ngModel at all, fixed style of cancel button on hover removed unused broken searchbar tests. references #247 --- ionic/components/searchbar/searchbar.ios.scss | 4 + ionic/components/searchbar/searchbar.ts | 81 +++++++++++-------- .../searchbar/test/floating/index.ts | 2 - .../searchbar/test/floating/main.html | 16 +++- .../components/searchbar/test/model/index.ts | 43 ---------- .../searchbar/test/toolbar/index.ts | 4 + 6 files changed, 69 insertions(+), 81 deletions(-) delete mode 100644 ionic/components/searchbar/test/model/index.ts diff --git a/ionic/components/searchbar/searchbar.ios.scss b/ionic/components/searchbar/searchbar.ios.scss index 71e146e473..563ecdb0f9 100644 --- a/ionic/components/searchbar/searchbar.ios.scss +++ b/ionic/components/searchbar/searchbar.ios.scss @@ -186,6 +186,10 @@ ion-searchbar { ion-searchbar[#{$color-name}] { .searchbar-ios-cancel { color: $color-value; + + &:hover:not(.disable-hover) { + color: color-shade($color-value); + } } } diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index b21738b375..33a5f101b9 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -1,10 +1,11 @@ -import {ElementRef, Component, Directive, Host, HostBinding, HostListener, ViewChild, Input, Output, EventEmitter} from 'angular2/core'; +import {ElementRef, Component, Directive, Host, HostBinding, HostListener, ViewChild, Input, Output, EventEmitter, Optional} from 'angular2/core'; import {NgIf, NgClass, NgControl, FORM_DIRECTIVES} from 'angular2/common'; import {Ion} from '../ion'; import {Config} from '../../config/config'; import {Icon} from '../icon/icon'; import {Button} from '../button/button'; +import {isDefined} from '../../util/util'; /** @@ -78,7 +79,7 @@ export class Searchbar extends Ion { @Output() clear: EventEmitter = new EventEmitter(); value: string = ''; - blurInput = true; + blurInput: boolean = true; @HostBinding('class.searchbar-focused') isFocused; @@ -98,43 +99,16 @@ export class Searchbar extends Ion { constructor( elementRef: ElementRef, config: Config, - ngControl: NgControl + @Optional() ngControl: NgControl ) { super(elementRef, config); + // If the user passed a ngControl we need to set the valueAccessor if (ngControl) { - this.ngControl = ngControl; - this.ngControl.valueAccessor = this; + ngControl.valueAccessor = this; } } - /** - * @private - * Write a new value to the element. - */ - public writeValue(value: any) { - this.value = value; - } - - public onChange = (_:any) => {}; - public onTouched = () => {}; - - /** - * @private - * Set the function to be called when the control receives a change event. - */ - public registerOnChange(fn:(_:any) => {}):void { - this.onChange = fn; - } - - /** - * @private - * Set the function to be called when the control receives a touch event. - */ - public registerOnTouched(fn:() => {}):void { - this.onTouched = fn; - } - /** * @private * On Initialization check for attributes @@ -149,9 +123,25 @@ export class Searchbar extends Ion { this.placeholder = this.placeholder || 'Search'; if (this.ngModel) this.value = this.ngModel; + this.onChange(this.value); + this.shouldLeftAlign = this.value && this.value.trim() != ''; } + /** + * @private + * After View Initialization check the value + */ + ngAfterViewInit() { + // If the user passes an undefined variable to ngModel this will warn + // and set the value to an empty string + if (!isDefined(this.value)) { + console.warn('Searchbar was passed an undefined value in ngModel. Please make sure the variable is defined.'); + this.value = ''; + this.onChange(this.value); + } + } + /** * @private * Sets the Searchbar to focused and aligned left on input focus. @@ -202,4 +192,31 @@ export class Searchbar extends Ion { this.clearInput(); this.blurInput = true; } + + /** + * @private + * Write a new value to the element. + */ + public writeValue(value: any) { + this.value = value; + } + + public onChange = (_:any) => {}; + public onTouched = () => {}; + + /** + * @private + * Set the function to be called when the control receives a change event. + */ + public registerOnChange(fn:(_:any) => {}):void { + this.onChange = fn; + } + + /** + * @private + * Set the function to be called when the control receives a touch event. + */ + public registerOnTouched(fn:() => {}):void { + this.onTouched = fn; + } } diff --git a/ionic/components/searchbar/test/floating/index.ts b/ionic/components/searchbar/test/floating/index.ts index f02e06b17a..d13a79cb3d 100644 --- a/ionic/components/searchbar/test/floating/index.ts +++ b/ionic/components/searchbar/test/floating/index.ts @@ -11,8 +11,6 @@ class E2EApp { defaultSearch: string = 'test'; customPlaceholder: string = ''; defaultCancel: string = ''; - customCancel: string = ''; - customCancelAction: string = ''; constructor() { diff --git a/ionic/components/searchbar/test/floating/main.html b/ionic/components/searchbar/test/floating/main.html index 3d135a58a2..49fde59f8c 100644 --- a/ionic/components/searchbar/test/floating/main.html +++ b/ionic/components/searchbar/test/floating/main.html @@ -3,15 +3,23 @@

- Default Search: {{ defaultSearch }} + defaultSearch: {{ defaultSearch }}

Search - Custom Placeholder
- + + +

+ customPlaceholder: {{ customPlaceholder }} +

Search - Hide Cancel Button
- + + +

+ defaultCancel: {{ defaultCancel }} +

Search - Custom Cancel Button Danger
- + diff --git a/ionic/components/searchbar/test/model/index.ts b/ionic/components/searchbar/test/model/index.ts deleted file mode 100644 index 9aeda952f4..0000000000 --- a/ionic/components/searchbar/test/model/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {NgControl, FORM_DIRECTIVES, FormBuilder, Validators, Control, ControlGroup} from 'angular2/common'; - -import {App} from 'ionic/ionic'; -import {SearchPipe} from 'ionic/components/searchbar/searchbar'; - - -function randomTitle() { - var items = ['Soylent', 'Pizza', 'Pumpkin', 'Apple', 'Bologna', 'Turkey', 'Kabob', 'Salad', 'Fruit bowl', 'Fish Tacos', 'Chimichongas', 'Meatloaf']; - return items[Math.floor(Math.random() * items.length)]; -} - -@App({ - templateUrl: 'main.html', - providers: [NgControl], - directives: [FORM_DIRECTIVES] -}) -class E2EApp { - constructor() { - var fb = new FormBuilder(); - - this.searchQuery = ''; - - this.items = [] - for(let i = 0; i < 100; i++) { - this.items.push({ - title: randomTitle() - }) - } - } - - getItems() { - var q = this.searchQuery; - if(q.trim() == '') { - return this.items; - } - return this.items.filter((v) => { - if(v.title.toLowerCase().indexOf(q.toLowerCase()) >= 0) { - return true; - } - return false; - }) - } -} diff --git a/ionic/components/searchbar/test/toolbar/index.ts b/ionic/components/searchbar/test/toolbar/index.ts index bf5a6c4b9d..a0c90e1e25 100644 --- a/ionic/components/searchbar/test/toolbar/index.ts +++ b/ionic/components/searchbar/test/toolbar/index.ts @@ -7,6 +7,10 @@ import {SearchPipe} from 'ionic/components/searchbar/searchbar'; templateUrl: 'main.html' }) class E2EApp { + defaultToolbarSearch: string = ''; + primaryToolbarSearch: string = ''; + dangerToolbarSearch: string = ''; + lightToolbarSearch: string = ''; constructor() {