sencha touch textfield clear event - sencha-touch

I'm trying to implement a list filter in a text field in sencha touch. For example, I'd have a bunch of contacts, and when I typed in the field, it might filter by name. When I click the circular X button to clear the textfield, I'd like to reset the filter to filter none of the contacts.
The problem is, I can't seem to figure out a way to detect the click on the clear button. There doesn't appear to be any type of event, and I can't seem to hack in a workaround.
If anyone has any idea how to detect a textfield clearing in sencha touch, I'd be much obliged.
I've tried in safari and xcode simulator, and am using sencha touch 1.1.0. Am I missing something? Is this not an issue when it's actually a mobile app?

You can listen for tap events on clearIconContainerEl inside the text field or override the onClearIconTap method.
Ext.setup({
icon: 'icon.png',
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
glossOnIcon: false,
onReady: function() {
var searchField = new Ext.form.Search({
name : 'search',
placeHolder: 'Search',
useClearIcon: true,
onClearIconTap: function() {
if (!this.disabled) {
this.setValue('');
console.log('onClearTap: Clear button tapped!');
}
}
});
var viewport = new Ext.Panel({
fullscreen: true,
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [searchField]
}]
});
console.log(searchField.useClearIcon);
searchField.mon(searchField.clearIconContainerEl, {
scope: searchField,
tap: function() {
if (!this.disabled) {
console.log('clearIconContainerEl: Clear button tapped!');
}
}
});
}
});

For sencha touch 2.0 users:
If your using new mvc structure, you can use this in the controller init
this.control({
'#yourTextFieldId clearicon': {
tap: function(){console.log('ClearICON tapped');}
}
....
)};

The problem is the little X is not added in by sencha touch. It is a feature of the "search" input with html5. To capture this event you need to look for the search event. How I solved this was I edited sencha-touch.js
I modified -
if (this.fieldEl) {
this.mon(this.fieldEl, {
focus: this.onFocus,
blur: this.onBlur,
keyup: this.onKeyUp,
paste: this.updateClearIconVisibility,
mousedown: this.onBeforeFocus,
scope: this
});
to be -
if (this.fieldEl) {
this.mon(this.fieldEl, {
focus: this.onFocus,
blur: this.onBlur,
keyup: this.onKeyUp,
paste: this.updateClearIconVisibility,
mousedown: this.onBeforeFocus,
search: this.onSearch,
scope: this
});
inside of Ext.form.Text = Ext.extend(Ext.form.Field, { ...
Now in my implementation of the searchfield I can make a function called onSearch which will be called when the "search" event is called. Note that the "search" event is not only called for the X but for some things like the enter key. The bottom line is sencha touch 1.1 does not check for this event at all and it is the only time the X fires an event so the only solution is to modify sencha-touch.js.

Related

How to perform View-Controller separation when using an "actioncolumn" (Ext.grid.column.Action)

In ExtJS 4, I have a grid that contains an action column. Whenever that action is triggered, I want to execute "my action".
Without MVC, this would look like this:
/* ... */
{
xtype: 'gridpanel',
columns: [
/* ... */
{
xtype: 'actioncolumn',
items: [{
handler: function(grid, rowIndex, colIndex) {
// my action
}
}]
}
]
}
Now I want to introduce the View-Controller separation. So I have to move the handler from the View to the Controller.
But how does the controller register its method to the action column? Looking at the ExtJS 4.1 actioncolumn docs, I can't find any event I could listen to. I also can't find a method to set the action column's handler afterwards.
So how can I achieve a clean View-Controller separation when using an actioncolumn?
Are actioncolumns not yet ready for MVC?
The problem is not in actioncolumn but in its items which are not ExtJs Widgets. This items are simple images. That's why we cannot assign handlers in control in such a way:
this.control({
'mygrid actioncolumn button[type=edit]' : this.onEdit
This way, however, would be the best one.
Unfortunately this way is impossible. But There is another way, which is almost as clean as the preferred one: make actioncolumn handler to fire grid's custom event (created by you):
// view
{
xtype: 'actioncolumn',
items: [{
icon: 'http://cdn.sencha.io/ext-4.1.0-gpl/examples/shared/icons/fam/cog_edit.png',
tooltip: 'Edit',
handler: function(grid, rowIndex, colIndex) {
// fire custom event "itemeditbuttonclick"
this.up('grid').fireEvent('itemeditbuttonclick', grid, rowIndex, colIndex);
}},
// controller
init: function() {
this.control({
'viewport > testpanel': {
itemeditbuttonclick: this.onEdit,
itemdeletebuttonclick: this.onDelete
}
});
},
Example
Here is demo.
This post explains an even simpler method than the accepted answer, if you only happen to have one type of actioncolumn item in your grid:
http://mitchellsimoens.com/actioncolumn-and-mvc/
Basically: just listen for the actioncolumn's click event in your controller. However, this doesn't work if you need to distinguish between multiple actioncolumn types.

Sencha Touch 2.0: Universal Ext.TitleBar title not changing

I am trying to create a universal titlebar with a back button for my application. I am including it in the various views by using {xclass:mUserStories.view.titlebar}.
Here is the code for the titlebar:
Ext.define('mUserStories.view.titlebar', {
extend: 'Ext.TitleBar',
id: 'narwhal',
config: {
docked: 'top',
// id: 'narwhal',
title: 'CHW Module',
items: [{
ui: 'back',
text: 'Back',
id: 'backButton'
// hidden: true
}]
}
})
However, when I try to dynamically change the toolbar when switching to different pages, the console.log of the titlebar says the _title has changed but the text on the titlebar and the "hidden" property of the button does not change.
Here is the code for the logic that occurs when the button is pressed to switch the page:
toPage: function (arg) {
var t = Ext.getCmp('narwhal');
var b = Ext.getCmp('backButton');
console.log(t,b)
if (arg === PAGES.PATIENT_LIST) {
t.setTitle('Patient List');
b.setHidden(true)
}
Ext.getCmp('viewPort').setActiveItem(arg);
}
I have also tried to include a ref at the top for Narwhal : '#narwhal' and use var t = this.getNarwhal(), but this does not work either.
I am not sure if the problem lies with where the id is being kept, how the id is being called, or because the page is not refreshing properly. Any advice would help!
Thank you for your time :)
I have had the same situation in my project.
I managed to get everything to work like you want it by having a controller owning a reference to the title bar and listening to activeItemChange on my tabPanel.

Sencha Touch 2 - setActiveItem of card layout inside navigationview issue

I have an Ext.Panel with a card layout nested inside a navigation view. I did this to easily switch between a map and a list without having to pop and then push a whole different view (basically to avoid the animation). So, I have a button in the navigationBar that fires an action in the controller. This initial view, with a list, load fine, but the controller code to switch between the views (using setActiveItem()) does not work. No error message. I found something about a bug where you have to call show(). Although this works, it overlays the new activeItem (the Map, in this case) on top of the navigaionBar! (see screenshot). Also, if I just change activeItem to 1 in the config of the wrapper manually, it shows the map just fine, same as the list.
My wrapper panel looks like this:
Ext.define(ViewInfos.VendorWrapper.ViewName,{
extend: 'Ext.Panel',
id: ViewInfos.VendorWrapper.PanelId,
xtype: ViewInfos.VendorWrapper.Xtype,
config:
{
layout: 'card',
title: Resources.VendorsNearby,
activeItem: 0,
items: [
{
xtype: ViewInfos.VendorList.Xtype, //Initially shown, a list
},
{
xtype: ViewInfos.VendorMap.Xtype, //What I'm trying to show, a map
}
]
}
});
and here is my controller code:
Ext.define('OrderMapper.controller.VendorWrapper', {
extend: 'Ext.app.Controller',
config: {
refs: {
vendorMap: ViewInfos.VendorMap.Xtype,
vendorList: ViewInfos.VendorList.Xtype,
vendorWrapper: ViewInfos.VendorWrapper.Xtype,
main: ViewInfos.Main.Xtype,
vendorToggleButton: (ViewInfos.Main.Xtype + ' button[action=vendorViewToggle]')
},
control: {
vendorToggleButton:{
tap: function(){
var curView = this.getVendorWrapper().getActiveItem().id;
//active view == VendorList
if(curView == 'VendorList'){
//this shows up in the console
console.log('vendorToggleButton tapped, switching to map');
this.getVendorWrapper().setActiveItem(1);
//without this line, the view doesn't even change
this.getVendorWrapper().show();
this.getVendorToggleButton().setText('List');
}
//active view == VendorMap
else if (curView == 'VendorMap'){
console.log('vendorToggleButton tapped, switching to list');
this.getVendorWrapper().setActiveItem(0);
this.getVendorToggleButton().setText('Map');
}
}
}
}
}
And here is the screenshot of the wonky view that happens on this.getVendorWrapper().show()
Also, I tried changing the wrapper to a Carousel (instead of a regular panel with a card layout), and the carousel will swipe to change list/map but setActiveItem() STILL doesn't work.
I'm currently working on a navigation.View where there is basically 4 main views from where you can push other subview. I did it like this :
Ext.define('App.view.Navigation', {
requires: [
...
],
xtype: 'mainviews',
extend: 'Ext.navigation.View',
config: {
cls: 'content',
layout:{animation:false}, // or whatever animation you want for push and pop
navigationBar: {
...
},
items: [{
xtype: 'container',
layout:'card',
items: [{
xtype: 'mainview1',
},{
xtype: 'mainview2',
},{
xtype: 'mainview3',
},{
xtype: 'mainview4',
}]
}]
}
});
Then it's really easy to either set the active item of the navigation view or push subviews
For instance, in a controller it would be
this.getMainviews().setActiveItem(X); // X = 0,1,2 or 3
and
this.getMainviews.push(view); // view = the view your want to push
and these is the references :
refs:{
mainviews: 'mainviews'
}
Hope this helps
First of all, if you just want to avoid the animation on push/pop, add this config to your navigation view:
layout: {
animation: null
}
Generally, you should not call .show() on items that are inside your Ext.navigation.View instance. They will be added to Ext.Viewport directly, thus appearing to be on top of the navigation bar.
Have a look at this JSFiddle example, might give you a hint.

sencha touch - nestedlist - store all the fields' values of "activeItem of nestedlist"

i have a panel which should show the "description" field of "currently activeitem of nestedlist". nestedlist uses the model having fields:
id
text
description
when user taps on any item of nestedList [on selectionchange OR itemtap&backtap], i want to change description in the panel with description of "currently activeItem of nestedList".
Is this possible?
thanks for any help/solution/pointer.
The same problem I had today, and no solution had been found with a nested list, because no single field can be taken from a Ext.data.TreeStore. One solution could be that you have lots of "if-function 'do with all the ID's and then you give each ID a text. But that's not good.
I've decided to make a simple list.
if you want I can show you my solution for the simple list
ps.: I use Sencha Touch 1.1
Update:
NotesApp.views.NaviList = new Ext.List({
fullscreen: true,
flex: 1,
layout: 'card',
scroll: false,
useToolbar: false,
itemTpl: '{text}',
store: store,
listeners: {
itemtap: function (obj, idx, el, e) {
var record = this.store.getAt(idx);
var tle = record.get('text');
index = record.get('index');
NotesApp.views.notesListContainer.setActiveItem(index, { type: 'slide', direction: 'left' });
}
}
}
});
description:
My App has the name: "NotesApp".
"notesListContainer" is a Container where all my List are displayed. "index" is an ID that I get from the store and the calls list.
Now when you tap on my NaviList you set a new ActiveItem in this Container.
thanks a lot for the reply. I also tried using simple list with one Ext.button(back button in case of nestedlist). On itemtap and buttonclink, i change list's content by
var t = new Ext.data.Store and list.setStore(t).
Please let me know if there is any other better option to do it.

Sencha Touch - event listener for NestedList back button?

Sencha Touch 1.1.1 --
Is there a way to set up a listener to listen for click events on the Back button of a NestedList? I can only find examples of how to set up for clicks on the 'body' or 'el' element. How would you be more specific and target the NestedList's back button?
Many Thanks
Code so far
MyTest.views.Justacard = Ext.extend(Ext.NestedList, {
title: "The Title",
...
listeners: {
click: {
element: 'el', // ANYTHING HERE TO TARGET THE BACK BUTTON?
fn: function(){
// do action
}
}
}
});
Ext.reg('justacard', MyTest.views.Justacard);
On a side note: because the NestedList component adds the back button automatically, there's no opportuity to configure it and add a handler (I think).
PS: adding the following code (below title: for example) allows me to respond to the Back button clicks - however, it also removes all the normal Back button functionality and the NestedList no longer slides back to the parent list.
onBackTap: function() {
alert('boo');
}
Turning into a proper 'lumpy carpet' scenario ; )
Try
MyTest.views.Justacard = Ext.extend(Ext.NestedList, {
title: "The Title",
...
listeners: {
back: function() {
alert('back?');
}
}
});
or
onBackTap: function() {
this.callParent(arguments);
alert('boo');
}
P.S. Sorry, I didn't test this (just looked at sources)