NativeScript/tns-core-modules/ui/search-bar/search-bar.ios.ts
searchBarCancelButtonClicked should use owner._emit(SearchBarBase.cancelEvent) event and not owner._emit(SearchBarBase.clearEvent);
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
Hi @Blah2014,
Could you provide some more info about the need for this change for the SearchBar?
It would also help if you could provide some more information, what will be the expected behavior when the cancelEvent is fired?
A couple usages (ios SearchBar):
Hi @Blah2014,
Thank you for the description.
However, for the case, you could use dismissSoftInput method for iOS to force closing the keyboard on onClear event of the SearchBar. For example:
XML
<GridLayout rows="auto *" columns="*" class="p-20">
<SearchBar row="0" col="0" id="searchBar" hint="Search" text="" clear="onClear" submit="onSubmit" />
</GridLayout>
TypeScript
import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import {SearchBar} from "ui/search-bar"
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
page.bindingContext = new HelloWorldModel();
}
export function onClear(args){
var search:SearchBar = <SearchBar>args.object;
setTimeout(()=>{
search.dismissSoftInput();
}, 0)
}
Let me give you a better example, which will be required clearEvent and cancelEvent.
In iPhone open Safari browser, on searchBar focus keyboard will open, on Cancel keyboard will close, if you have a text in searchBar and click "x" clear button or will use keyboard clear text button searchBar will be cleared and keyboard will stay open, again on Cancel click the only keyboard will be closed.
I hope this example will clear things out...
You cannot replicate Safari searchBar behavior without clearEvent and cancelEvent unless you write hackish code.
If ios do have func searchBarCancelButtonClicked(UISearchBar) framework should preserve it, this will make developers live easy.
Hi @Blah2014,
Thank you for the detailed explanation.
Indeed such an event could be included for the SearchBar component for iOS. I will log this as a feature request and the other users could also vote about it. If there is an interest this functionality will be added for some of the next NativeScript versions.
In the meantime, you could overwrite the current delegate for the SearchBar component, which will allow you to handle searchBarCancelButtonClicked event.
Bear in mind that to show the default cancel button for the component similar to this on the Safari search, you could use setShowsCancelButtonAnimated() method.
For further help you could review the below-attached sample code snippet:
XML
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<GridLayout rows="auto *" columns="*" class="p-20">
<SearchBar loaded="searchBarLoaded" row="0" col="0" id="searchBar" hint="Search" text="" clear="onClear" submit="onSubmit" />
</GridLayout>
</Page>
TypeScript
import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import {SearchBar} from "ui/search-bar";
import {TextField} from "ui/text-field"
import { isIOS } from "platform";
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
page.bindingContext = new HelloWorldModel();
}
export function onClear(args){
var search:SearchBar = <SearchBar>args.object;
setTimeout(()=>{
search.dismissSoftInput();
}, 0)
}
export function tap(args){
var textObj:TextField = <TextField> args.object;
console.log("tap");
console.log(textObj);
}
export function searchBarLoaded(args){
var searchbar:SearchBar = <SearchBar>args.object;
console.log("searchbar loaded");
console.log(searchbar.ios);
searchbar.ios.setShowsCancelButtonAnimated(true, true)
let newDelegate = newUISearchBarDelegate.initWithOriginalDelegate((<any>searchbar)._delegate);
(<any>searchbar)._delegate=newDelegate;
}
class newUISearchBarDelegate extends NSObject implements UISearchBarDelegate {
public static ObjCProtocols = [UISearchBarDelegate];
private _originalDelegate: UISearchBarDelegate;
public static initWithOriginalDelegate(originalDelegate: UISearchBarDelegate): newUISearchBarDelegate {
console.log("initWithOwner")
let delegate = <newUISearchBarDelegate>newUISearchBarDelegate.new();
delegate._originalDelegate = originalDelegate;
console.log(delegate);
console.log(delegate._originalDelegate);
return delegate;
}
public searchBarTextDidChange(searchBar: UISearchBar, searchText: string) {
return this._originalDelegate.searchBarTextDidChange(searchBar, searchText);
}
public searchBarCancelButtonClicked(searchBar: UISearchBar) {
console.log("searchBarCancelButtonClicked");
this._originalDelegate.searchBarCancelButtonClicked(searchBar);
}
public searchBarSearchButtonClicked(searchBar: UISearchBar) {
this._originalDelegate.searchBarSearchButtonClicked(searchBar);
}
}
Sounds good,
Can you provide overwrite the current delegate example for Nativescript + Angular if you don't mind?
This may be helpful to other developers...
Thank you
Hi @Blah2014,
The implementation for NativeScript Angular 2 project is pretty the same. The only difference is in the way, how you should register SearchBar loaded event in the XML.
HTML
<ActionBar title="My App" class="action-bar">
</ActionBar>
<StackLayout class="page">
<GridLayout rows="auto *" columns="*" class="p-20">
<SearchBar (loaded)="searchBarLoaded($event)" row="0" col="0" id="searchBar" hint="Search" text="" class="search-bar"></SearchBar>
</GridLayout>
</StackLayout>
TypeScript
import { Component, OnInit } from "@angular/core";
import {SearchBar} from "ui/search-bar";
@Component({
selector: "ns-items",
moduleId: module.id,
templateUrl: "./items.component.html",
})
export class ItemsComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
searchBarLoaded(args){
var searchbar:SearchBar = <SearchBar>args.object;
console.log("searchbar loaded");
console.log(searchbar.ios);
searchbar.ios.setShowsCancelButtonAnimated(true, true)
let newDelegate = newUISearchBarDelegate.initWithOriginalDelegate((<any>searchbar)._delegate);
(<any>searchbar)._delegate=newDelegate;
}
}
class newUISearchBarDelegate extends NSObject implements UISearchBarDelegate {
public static ObjCProtocols = [UISearchBarDelegate];
private _originalDelegate: UISearchBarDelegate;
public static initWithOriginalDelegate(originalDelegate: UISearchBarDelegate): newUISearchBarDelegate {
console.log("initWithOwner")
let delegate = <newUISearchBarDelegate>newUISearchBarDelegate.new();
delegate._originalDelegate = originalDelegate;
console.log(delegate);
console.log(delegate._originalDelegate);
return delegate;
}
public searchBarTextDidChange(searchBar: UISearchBar, searchText: string) {
return this._originalDelegate.searchBarTextDidChange(searchBar, searchText);
}
public searchBarCancelButtonClicked(searchBar: UISearchBar) {
console.log("searchBarCancelButtonClicked");
this._originalDelegate.searchBarCancelButtonClicked(searchBar);
}
public searchBarSearchButtonClicked(searchBar: UISearchBar) {
this._originalDelegate.searchBarSearchButtonClicked(searchBar);
}
}
Bear in mind that you should also install tns-platform-declarations plugin. More about setting up those declarations could be found here.
Also interested in this. I currently have:
public tap() {
this.searchBar.ios.setShowsCancelButtonAnimated(true, true);
}
Which is great to go from no cancel button to cancel button. But I also want to set (false, true) on cancel click, but the only way to access searchBarCancelButtonClicked is through your delegate code, which I'm less than excited about as a permanent solution.
Hi, is it possible to change the color for cancel button?
+1, would be great if the SearchBar can have the focus and blur event as the TextView has.
Hi, is it possible to change the color for cancel button?
Yes it is possible, let me know you still need this
Can you provide the current delegate example for Nativescript + Vue using Javascript if you don't mind?
This may be helpful to other developers using nativescript-vue with javascript
Thank you
Most helpful comment
Hi @Blah2014,
Thank you for the detailed explanation.
Indeed such an event could be included for the
SearchBarcomponent foriOS. I will log this as a feature request and the other users could also vote about it. If there is an interest this functionality will be added for some of the next NativeScript versions.In the meantime, you could overwrite the current delegate for the
SearchBarcomponent, which will allow you to handlesearchBarCancelButtonClickedevent.Bear in mind that to show the default cancel button for the component similar to this on the Safari search, you could use
setShowsCancelButtonAnimated()method.For further help you could review the below-attached sample code snippet:
XML
TypeScript