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 bd7215803c..33a5f101b9 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -1,11 +1,35 @@ -import {ElementRef, Renderer, Directive, Host, forwardRef, ViewChild, 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 {ConfigComponent} from '../../decorators/config-component'; import {Icon} from '../icon/icon'; import {Button} from '../button/button'; +import {isDefined} from '../../util/util'; + + +/** +* @private +*/ +@Directive({ + selector: '.searchbar-input', +}) +export class SearchbarInput { + @HostListener('input', ['$event']) + /** + * @private + * Don't send the input's input event + */ + private stopInput(ev) { + event.preventDefault(); + event.stopPropagation(); + } + + constructor(elementRef: ElementRef) { + this.elementRef = elementRef; + } +} + /** * @name Searchbar @@ -15,65 +39,74 @@ 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. + * @property {Any} [clear] - Expression to evaluate when the clear input 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; - blurInput = true; + @ViewChild(SearchbarInput) searchbarInput; + + @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(); + + value: string = ''; + blurInput: boolean = true; + + @HostBinding('class.searchbar-focused') isFocused; + + @HostBinding('class.searchbar-left-aligned') shouldLeftAlign; + + @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); + } constructor( elementRef: ElementRef, config: Config, - ngControl: NgControl, - renderer: Renderer + @Optional() ngControl: NgControl ) { super(elementRef, config); - 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 = ''; + // If the user passed a ngControl we need to set the valueAccessor + if (ngControl) { + ngControl.valueAccessor = this; + } } /** @@ -88,14 +121,25 @@ export class Searchbar extends Ion { this.cancelButtonText = this.cancelButtonText || 'Cancel'; 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 the view has initialized check if the Searchbar has a value + * After View Initialization check the value */ ngAfterViewInit() { - this.shouldLeftAlign = this.searchbarInput.value && this.searchbarInput.value.trim() != ''; + // 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); + } } /** @@ -120,9 +164,8 @@ 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() != ''; + this.shouldLeftAlign = this.value && this.value.trim() != ''; } /** @@ -130,9 +173,10 @@ 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.clear.emit(this); + + this.value = ''; + this.onChange(this.value); this.blurInput = false; } @@ -142,69 +186,29 @@ 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() { + this.cancel.emit(this); + this.clearInput(); this.blurInput = true; - - this.cancelButtonAction && this.cancelButtonAction(event, value); - } - - /** - * @private - * Updates the value of query - */ - updateQuery(value) { - this.query = value; - this.input.next(value); - } -} - -/** -* @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) { + public writeValue(value: any) { this.value = value; - if (typeof value === 'string') { - this.searchbar.updateQuery(value); - } } + public onChange = (_:any) => {}; + public onTouched = () => {}; + /** * @private * Set the function to be called when the control receives a change event. */ - registerOnChange(fn) { + public registerOnChange(fn:(_:any) => {}):void { this.onChange = fn; } @@ -212,17 +216,7 @@ export class SearchbarInput { * @private * Set the function to be called when the control receives a touch event. */ - registerOnTouched(fn) { + public registerOnTouched(fn:() => {}):void { 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..d13a79cb3d 100644 --- a/ionic/components/searchbar/test/floating/index.ts +++ b/ionic/components/searchbar/test/floating/index.ts @@ -8,27 +8,23 @@ 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; + onClearSearchbar(searchbar) { + console.log("Clicked clear input on", searchbar); } - 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); - }); + onCancelSearchbar(searchbar) { + console.log("Clicked cancel button with", searchbar); + } + + triggerInput(searchbar) { + console.log("Triggered input", searchbar); } } diff --git a/ionic/components/searchbar/test/floating/main.html b/ionic/components/searchbar/test/floating/main.html index 27eecacf83..49fde59f8c 100644 --- a/ionic/components/searchbar/test/floating/main.html +++ b/ionic/components/searchbar/test/floating/main.html @@ -1,24 +1,25 @@
Search - Default
- +

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

Search - Custom Placeholder
- + + +

+ customPlaceholder: {{ customPlaceholder }} +

Search - Hide Cancel Button
- + + +

+ defaultCancel: {{ defaultCancel }} +

Search - Custom Cancel Button Danger
- - -
Search - Custom Cancel Action
- - -
- Clicked custom action with input = {{customCancelAction}} -
+
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() { 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) {