Sencha Touch - deselect list item? - javascript

I'm working on a Sencha Touch application, and have a list of contacts. When a list item is tapped, an ActionSheet is displayed showing some basic functions (such as call, delete and ignore). Unfortunately, when the user taps and the ActionSheet is fired, the List item remains selected underneath the overlay (see the screenshot below):
Here's the function bound to the itemTap event:
itemTap: function(list, index)
{
// Deselect the selected record:
var currentRecord = list.getStore().getAt(index);
currentRecord.forename = currentRecord.get('forename');
currentRecord.surname = currentRecord.get('surname');
currentRecord.phoneNumber = currentRecord.get('phoneNumber');
currentRecord.shortFullName = currentRecord.forename + ' ' + currentRecord.surname[0];
list.getStore().deselect(index, true);
callButton.setText('Call ' + currentRecord.shortFullName + ' (' + currentRecord.phoneNumber + ')');
unfriendButton.setText('Remove ' + currentRecord.shortFullName + ' as friend');
friendActionSheet.show();
}
Unfortunately, list.getStore().deselect(index, true) returns the following error: Object [object Object] has no method 'deselect'
Any ideas on what I could be doing wrong, or how I can achieve this?

This works for me:
listeners: {
itemtap: function(dv, ix, item, e) {
// Clear the selection soon
setTimeout(function(){dv.deselect(ix);},500);
}
}

In Sencha Touch 2, use disableSelection: true, while creating a list
Ext.define('App.view.NewsList',{
extend: 'Ext.List',
xtype: NEWS_LIST,
config: {
store: NEWS_FEED,
//deselectOnContainerClick: true,// not working in Sencha Touch 2
disableSelection: true, // since Sencha Touch 2
itemTpl: '{heading}'
}
});

If you want to clear the whole list:
var selModel = app.views.notesList.deselect(app.views.notesList.getSelectedRecords());

setTimeout is really not a good solution here. It should be like this:
listeners: {
itemtap: function(list, ix, item, e) {
// Clear the selection soon
list.deselect(list.getSelectedRecords());
}
}

I haven't tried to recreate your problem but you may want to try:
list.deselect(currentRecord, true);
After you do that you may have to call
doLayout()
or
doComponentLayout()
to refresh the view.

This drove me INSANE.
While the approved answer will work, its worth noting that you can do it with a delay(like nested list does too) like this:
var selModel = app.views.VideosList.items.items[0].getSelectionModel();
Ext.defer(selModel.deselectAll, 200, selModel);
I put that in my controller (so its called when the view changes), where app.views.VideosList is my main panel and app.views.VideosList.items.items[0] is the list in that panel.

this did it for me (sencha touch 2.3):
list = Ext.Viewport.down('nestedlist');
list.getActiveItem().deselectAll();

Related

Component lost during rerender, how to reattach?

I am rendering a component into a grid rowExpander plugin rowBodyTpl:
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : [
'<div id="contact-row-{Id}"> </div>'
]
}],
var row = 'contact-row-' + record.get('Id'),
grid = Ext.getCmp(gridId),
if(!grid) me.createSubGrid(record,gridId).render(row);
This works fine. But when the grid receives an update event for a record with certain modifiedFields, that record's rowExpander is rerendered using the rowTpl only, and the inner grid is dangling somewhere. I can access the grid using Ext.getCmp, and grid.rendered is true, but it is not shown. So I guess I have to reattach the grid after the row has been rerendered.
I think I can attach to the update event, and find out whether the rowTpl has been rerendered without the child grid using
if(!grid.container.contains(grid.el))
But is there a way to put the grid back into the dom?
I have tried
grid.container.insertFirst(grid.el);
but this does not work. The element is inserted but the grid is not displayed.
Any ideas?
The way you are doing leads to memory leaks (because your component is not destroy when the grid is re-render).
I suggest to check at : Component Template (http://skirtlesden.com/ux/ctemplate) or if you try to render a nested grid, there was several attempt to build something correct and I think a working one is the following : http://blogs.walkingtree.in/2015/06/30/nested-grid-in-sencha-ext-js/
With my trials, I already was on the right track, and the error was somewhere else entirely. The problem was that my update event fn which did the reattach was executed before the update event fn that broke everything, because the fn was fired on the same event and had the same priority, but was attached to the store earlier. Changing the priority was one option, but I just put the creation into the boxready event, which is executed after the view has attached its events to the store:
xtype:'grid',
listeners:{
boxready:function(grid) {
var store = grid.getStore();
...
store.on({
update:function(store, record) {
me.restoreSubgridDom(record);
},
beforeload:function(store) {
var records = store.getRange();
Ext.each(records,me.destroySubgrid);
}
});
}
}
with the two functions:
restoreSubgridDom: function(record) {
var row = 'contact-row-' + record.get('Id'),
gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid && !grid.container.contains(grid.el))
{
grid.container.insertFirst(grid.el);
}
},
destroySubgrid: function(record) {
var gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid) grid.destroy();
}

Extjs 5.1 Dynamic addition of container to panel

What i am trying to do is dynamically add container to panel on click of button.
1st instance of container gets added and can be seen in the panel.items.length
2nd instance onwards the panel.items.length doesn't change. but the panel can be seen in dom and on screen.
Just wanted to know why the panel.items.length is not increasing. Is it a bug?
Fiddler link https://fiddle.sencha.com/#fiddle/p3u
Check for the line :
console.log(qitems);
below debugger; it is set to questionsblock.items.length that i am talking about.
Remove the itemId from QuestionTemplate and remove renderTo from the new instance.
Your click handler should look like this:
listeners: {
'click': function(button) {
var questionPanel = button.up('form').down('#questionsblock'),
qitems = questionPanel.items.length,
questiontemplate = Ext.create('QuestionTemplate', {
qid: qitems,
questiontype: 'text'
});
console.log(qitems);
questionPanel.add(questiontemplate);
questionPanel.doLayout();
}
}
Check this fiddle: https://fiddle.sencha.com/#fiddle/p47

Kendo Grid Is there an event for when a row changes (not selected)?

I was hoping to detect when a Kendo grid's row changes, by navigation as opposed to selecting.
By this I mean I would have a grid with selectable: false, in batch edit mode, and I would like to update the data source (in code) when the user tabs to a new row (just as Access does).
I have looked at this example and changed the following properties..
selectable: false,
navigatable: true,
editable: true,
Unfortunately the changed event does not when seem to fire for tabs or arrow keys (when in navigation mode).
Would anyone know any other way I can do as described above (ie know when we have changed row via navigation)
Thanks in advance for any help!
You can use the edit event to determine whether you're in a new row.
Here you go:
selectable: false,
navigatable: true,
editable: true,
edit: function(e) {
if (e.sender.cellIndex($(e.container)) === 0 &&
$(e.container).closest("tr").index() !== 0) {
console.log("next row; update DS");
}
},
You could also store the last row you were in and determine the change using that, if switching between rows in other ways than by tabbing (or when tabbing backwards) is relevant.
If you don't want the grid to be editable, it's more difficult. Here's a quick hack:
var grid = $("#grid").data("kendoGrid");
var elem = $(grid.table)[0];
var handlers = $._data(elem, "events")["keydown"][2];
var oldHandler = handlers.handler;
// replace the existing event handler attached by kendo grid
var newHandler = function (e) {
oldHandler(e);
var current = grid.current();
var closestRow = $(current).closest("tr");
var rowIndex = $(closestRow).index();
if (rowIndex !== grid._lastNavRowIndex) {
if (typeof grid._lastNavRowIndex !== "undefined") {
kendoConsole.log("we just changed to row " + rowIndex);
}
grid._lastNavRowIndex = rowIndex;
}
};
handlers.handler = newHandler;
});
Try it here.
This is probably what you are looking for. When you want events related to the data, you have to look for the DataSource events. When you want events related to the UI, than you look at the Grid events.

Extjs 4.1.1a Check symbol of Checkbox on grid panel doesn't work

on a tab panel I create a tab for each year I have in a database (in this case the database contains at the moment only 3 years: 2012, 2013 ans 2014) and finally I set as active tab the current year (2013). In the controller I do the following:
var tp= this.getTpOverview();
this.getPlannedYearsStore().load({
callback: function(records) {
for (i=0; i< records.length; i++){
var year = records[i].data.year;
var tab = tp.add({
title: year,
year: year,
layout:'fit',
listeners: {
activate: function() {
var tbOverview = Ext.getCmp('tabOverview-'+ this.year);
if (!tbOverview) {
var gridOverview = Ext.create('WLPT.view.CPAssMonthActHours', {
id: 'tabOverview-' + this.year,
year: this.year,
xtype: 'cpassmonthacthoursview',
autoScroll: true
});
this.add(gridOverview);
} else {
selectedYear = this.year;
tbOverview.getStore().load({
params : {
wrk_year: selectedYear
}
});
}
}
}
});
if (currentYear == parseInt(records[i].data.year)) {
tab2Activate = tab;
}
}
tp.setActiveTab(tab2Activate);
}
});
When I run the application this seams to work fine.
I forgot to say that each tab contains a grid panel with a check column (Checkbox model) and for each item (row) a cell editor is setted on selected cells.
The active tab (2013) works fine. I can check the checkboxes to perfom a sum of the selected items. Indeed, the cell editor works fine.
The problem appears when I change the tab. The corresponding grid comes with the checkbox column. But on the javascript console appears the following error message:
Uncaught TypeError: Cannot call method 'setWidth' of undefined ext-all-debug.js:95689
Ext.define.onColumnResize ext-all-debug.js:95689
Ext.define.onColumnResize ext-all-debug.js:101362
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.onHeaderResize ext-all-debug.js:97344
Ext.define.afterComponentLayout ext-all-debug.js:98063
Ext.define.notifyOwner ext-all-debug.js:28381
Ext.define.callLayout ext-all-debug.js:103511
Ext.define.flushLayouts ext-all-debug.js:103680
Ext.define.runComplete ext-all-debug.js:104194
callOverrideParent ext-all-debug.js:54
Base.implement.callParent ext-all-debug.js:3813
Ext.override.runComplete ext-all-debug.js:21234
Ext.define.run ext-all-debug.js:104175
Ext.define.statics.flushLayouts ext-all-debug.js:21238
Ext.define.statics.resumeLayouts ext-all-debug.js:21246
Ext.resumeLayouts ext-all-debug.js:23343
Ext.define.setActiveTab ext-all-debug.js:111589
Ext.define.onClick ext-all-debug.js:111357
(anonymous function)
Ext.apply.createListenerWrap.wrap
Despite that, the grid is shown correctly. But, when I select a item the javascript console shows the following error message:
Uncaught TypeError: Cannot call method 'up' of null ext-all-debug.js:99591
Ext.define.onRowFocus ext-all-debug.js:99591
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.focusRow ext-all-debug.js:92462
Ext.define.onRowFocus ext-all-debug.js:92423
Ext.define.onLastFocusChanged ext-all-debug.js:109495
Ext.define.setLastFocused ext-all-debug.js:83855
Ext.define.doMultiSelect ext-all-debug.js:83761
Ext.define.doSelect ext-all-debug.js:83721
Ext.define.selectWithEvent ext-all-debug.js:83623
Ext.define.onRowMouseDown ext-all-debug.js:109750
Ext.util.Event.Ext.extend.fire ext-all-debug.js:8896
Ext.define.continueFireEvent ext-all-debug.js:9102
Ext.define.fireEvent ext-all-debug.js:9080
Ext.override.fireEvent ext-all-debug.js:51104
Ext.define.processUIEvent ext-all-debug.js:85315
Ext.define.handleEvent ext-all-debug.js:85227
(anonymous function)
Ext.apply.createListenerWrap.wrap
The selection on the item fires the event 'select' and 'deselect' when I click a second time. But the check symbol on the checkbox doesn't work any time.
I have thougth to put this symbol manually on the events 'select' and 'deselect' as a workaround, but I don't know how to put this style and which one is.
Do you have any ideas? Look forward for your suggestions. Thank you in advance.
Manuel
I think, the errors are not related to the code you posted. In fact, your code does not set the width, nor does it call up.
I find your code convoluted: a callback with a listener inside, that creates a view inside. And I don't understand if your code is inside a controller or another class.
Here is a problem:
var tab = tp.add({
//xtype is missing
title: year,
For debugging, I can giv you the following recommendation:
Use ext-dev.js instead of ext-all-debug.js. This will load all required classes one after the other, and the errors in the backtrace are not all inside ext-all-debug.js, but each line shows the line in the source class with all comments in it.
To get a cleaner programming style, try to follow the MVC pattern strictly:
Folder structure as recommended
Define events in the controller, like
init: function(){
this.listen({
store: {
'#plannedYearsStore': {load: this.onPlannedYearsStoreLoad}
}
})
this.control({
'tab': {activate: this.onTabActivate}
})
},
onPlannedYearsStoreLoad: function (store, records){
for (i=0; i< records.length; i++){
var year = records[i].data.year;
var tab = tp.add({
...
},
onTabActivate: function (){
var tbOverview = Ext.getCmp('tabOverview-'+ this.year);
...
},
If possible, define your tab in a view class in a separate file.
When you adhere striclty to this MVC structure, you will get a much easier maintainable code.

ExtJS 4 DataView inside TabPanel

In my MVC application in Controller i have following function to add and focus new tab to TabPanel with DataView inside:
show_gallery: function(view, record, item, index, e, opts) {
var tabb = Ext.ComponentQuery.query('.gallery_panel');
var gallery_view = Ext.widget('gallery_view');
var ImageStore = Ext.create('Gallery.store.Images');
ImageStore.load({url: 'myphoto/index.php/api/feed/json/' + record.data.uuid});
Ext.apply(gallery_view, {
title: record.data.name,
id: record.data.uuid,
closable:true,
store: ImageStore
});
if (tabb[0].down('#' + record.data.uuid)) {
console.log('Entered IF');
//tabb[0].setActiveTab(tabb[0].down('#' + record.data.uuid));
tabb[0].setActiveTab(record.data.uuid);
}else{
console.log('Entered ELSE');
tabb[0].add(gallery_view);
if (Ext.getCmp(record.data.uuid)) {
console.log('THERE IS SUCH UUID');
}
//tabb[0].setActiveTab(gallery_view);
}
},
And the problem is in the last line. When i uncomment tabb[0].setActiveTab(gallery_view) the new tab is focused but empty and if i leave the line commented the new tab with dataView is populated with data but not focused. I really dont have any idea why setActiveTab() causes DataView not to display at all. The gallery_view widget is Ext.view.View extension.
I'm not sure how come you get the data view if there's no setActiveTab, but there seem to be some issue with this code:
var gallery_view = Ext.widget('gallery_view');
var ImageStore = Ext.create('Gallery.store.Images');
ImageStore.load({url: 'myphoto/index.php/api/feed/json/' + record.data.uuid});
Ext.apply(gallery_view, {
title: record.data.name,
id: record.data.uuid,
closable:true,
store: ImageStore
});
First you create a new widget with Ext.widget() and then you override some config options with Ext.apply(). To my understanding, the latter is fine for primitives but not for objects/arrays.
Generally speaking, the configs are there for the purpose of telling the constructor how to initialise a specific instance of the class. A change to an object's title through Ext.apply() could work if the object is not rendered yet, but not a change to a store config (upon construction the component might start listening to various store events, this won't happen by a simple Ext.apply() which only copies configs from one object to another - you've already missed the train for a component that was created as far as listening to store events goes).
Please try this instead:
var ImageStore = Ext.create('Gallery.store.Images');
ImageStore.load({url: 'myphoto/index.php/api/feed/json/' + record.data.uuid});
var gallery_view = Ext.widget('gallery_view', {
title: record.data.name,
id: record.data.uuid,
closable:true,
store: ImageStore
});

Categories