-
7 Mar 2012 5:24 AM #1
NestedList and data disclosure property lead to exception.
NestedList and data disclosure property lead to exception.
guys,
I've found an issue when using the nestedlist in combination with disclosure property on the data.
Actually there are two ways to use disclosure:
1. show disclosure on all items on the list
2. show disclosure only on items where the data of the node has a property called disclosure which must be a boolean.
I used the second option and run into following issue:
1. go down the hierarchy of the nested list for minimum two levels (to use the first/ second list that are used internally). where disclosures have been set
2. go to the third level where minimum one item has no disclosure.
3. go back to start level.
On the last back click an exception will be raised in this line:
(Ext.dataview.element.List: updateListItem method)
This issue is raised by this method:Code:if (disclosure && dataview.getOnItemDisclosure()) { disclosureEl = extItem.down(me.disclosureClsCache); disclosureEl[disclosure ? 'removeCls' : 'addCls'](me.hiddenDisplayCache); }
(Ext.dataview.element.List: getItemElementConfig method)
As you can see, the classes that are going to be added will miss a space in between which leads to the actual problem that it cannot be found afterwards.Code:if (dataview.getOnItemDisclosure()) { config.children.push({ cls: me.disclosureClsShortCache + ((data.disclosure === false) ? me.hiddenDisplayCache : '') }); }
Version is 2.0.0. RC1, but it looks like issue is still available in release.
Override can be done like this:
Code:Ext.define('Ext.dataview.element.ListOverride', { override: 'Ext.dataview.element.List', getItemElementConfig: function(index, data) { var me = this, dataview = me.dataview, itemCls = dataview.getItemCls(), cls = me.itemClsShortCache, config, iconSrc; if (itemCls) { cls += ' ' + itemCls; } config = { cls: cls, children: [{ cls: me.labelClsShortCache, html: dataview.getItemTpl().apply(data) }] }; if (dataview.getIcon()) { iconSrc = data.iconSrc; config.children.push({ cls: me.iconClsShortCache, style: 'background-image: ' + iconSrc ? 'url("' + newSrc + '")' : '' }); } if (dataview.getOnItemDisclosure()) { config.children.push({ cls: me.disclosureClsShortCache + ' ' + ((data.disclosure === false) ? me.hiddenDisplayCache : '') }); } return config; } });
-
7 Mar 2012 6:23 AM #2Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 33,714
- Vote Rating
- 438
Nice catch. Here is my test case:
With JSON:Code:Ext.define('File', { extend: 'Ext.data.Model', config: { fields: [ {name: 'id', type: 'string'}, {name: 'fileName', type: 'string'}, 'disclosure' ] } }); var store = Ext.create('Ext.data.TreeStore', { model: 'File', autoLoad: true, proxy: { type: 'ajax', url: 'data/json.json' } }); Ext.create('Ext.NestedList', { fullscreen: true, title: 'src/', displayField: 'fileName', listConfig : { onItemDisclosure : true }, // add a / for folder nodes in title/back button getTitleTextTpl: function() { return '{' + this.getDisplayField() + '}<tpl if="leaf !== true">/</tpl>'; }, // add a / for folder nodes in the list getItemTextTpl: function() { return '{' + this.getDisplayField() + '}<tpl if="leaf !== true">/</tpl>'; }, store: store });
I go to form -> field and then try to go back twice and I get the removeCls error. With your override it looks to work so we will look at it! Thank you.Code:{ "children": [ { "cls": "file", "fileName": "Ajax.js", "id": "./Ajax.js", "leaf": true, "disclosure" : false }, { "cls": "folder", "fileName": "form", "id": "./form", "children": [ { "fileName": "Panel.js", "id": "form/Panel.js", "leaf": true, "cls": "file", "disclosure" : false }, { "fileName": "Field", "id": "field/Field", "cls": "folder", "children": [ { "fileName": "Number.js", "id": "field/Number.js", "leaf": true, "cls": "file" }, { "fileName": "Text.js", "id": "field/Text.js", "leaf": true, "cls": "file", "disclosure" : false } ] } ] }, { "cls": "folder", "fileName": "util", "id": "./util", "children": [ { "fileName": "TapRepeater.js", "id": "util/TapRepeater.js", "leaf": true, "cls": "file" } ] } ], "text": "." }
btw, here is your override but formatted:
Code:Ext.define('Ext.dataview.element.ListOverride', { override: 'Ext.dataview.element.List', getItemElementConfig: function(index, data) { var me = this, dataview = me.dataview, itemCls = dataview.getItemCls(), cls = me.itemClsShortCache, config, iconSrc; if (itemCls) { cls += ' ' + itemCls; } config = { cls: cls, children: [{ cls: me.labelClsShortCache, html: dataview.getItemTpl().apply(data) }] }; if (dataview.getIcon()) { iconSrc = data.iconSrc; config.children.push({ cls: me.iconClsShortCache, style: 'background-image: ' + iconSrc ? 'url("' + newSrc + '")' : '' }); } if (dataview.getOnItemDisclosure()) { config.children.push({ cls: me.disclosureClsShortCache + ' ' + ((data.disclosure === false) ? me.hiddenDisplayCache : '') }); } return config; } });Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
13 Mar 2012 9:04 AM #3
Actually I found a second issue right in the same class.
There is an issue updating disclosure items when moving between the pages.
As I already mentioned above I use the disclosure like this:
2.. show disclosure only on items where the data of the node has a property called disclosure which must be a boolean.
Follow these steps to reproduce:
1. go down the hierarchy of the nested list for minimum two levels (to use the first/ second list that are used internally). where disclosures have been set. Make sure that on the last page there is at least one item that has disclosure set to false. (so there are not all disclosures shown). It does make sense to have the first item set to false as you'll only see the issue when the item is updated later on.
2. go back to root level.
3. the item that does not have the disclosure item was incorrectly updated, missing disclosure item now.
Original code looks like this (line 58786, Ext.dataview.element.List.updateListItem):
Here as usual the fix.(comments highlighted)Code:if (disclosure && data[disclosureProperty] === false) { disclosureEl = extItem.down(me.disclosureClsCache); disclosureEl[disclosure ? 'removeCls' : 'addCls'](me.hiddenDisplayCache); }
Code:Ext.define('Flexreport.overrides.ExtdataviewelementList', { override: 'Ext.dataview.element.List', getItemElementConfig: function (index, data) { var me = this, dataview = me.dataview, itemCls = dataview.getItemCls(), cls = me.itemClsShortCache, config, iconSrc; if (itemCls) { cls += ' ' + itemCls; } config = { cls: cls, children: [{ cls: me.labelClsShortCache, html: dataview.getItemTpl().apply(data) }] }; if (dataview.getIcon()) { iconSrc = data.iconSrc; config.children.push({ cls: me.iconClsShortCache, style: 'background-image: ' + iconSrc ? 'url("' + newSrc + '")' : '' }); } if (dataview.getOnItemDisclosure()) { // actually here is an issue as the original code missing the space between the classes. config.children.push({ cls: me.disclosureClsShortCache + ' ' + ((data.disclosure === false) ? me.hiddenDisplayCache : '') }); } return config; }, updateListItem: function(record, item) { var me = this, dataview = me.dataview, extItem = Ext.fly(item), innerItem = extItem.down(me.labelClsCache, true), data = record.data, disclosureProperty = dataview.getDisclosureProperty(), disclosure = data && data.hasOwnProperty(disclosureProperty), iconSrc = data && data.hasOwnProperty('iconSrc'), disclosureEl, iconEl; innerItem.innerHTML = dataview.getItemTpl().apply(data); // actually here is a difference, original code additionally asks for the value of disclosure is false which is not sensible as this // case here handles both. if (disclosure) { disclosureEl = extItem.down(me.disclosureClsCache); disclosureEl[disclosure ? 'removeCls' : 'addCls'](me.hiddenDisplayCache); } if (dataview.getIcon()) { iconEl = extItem.down(me.iconClsCache, true); iconEl.style.backgroundImage = iconSrc ? 'url("' + iconSrc + '")' : ''; } } });
-
14 Mar 2012 1:21 PM #4Sencha - Sencha Touch Dev Team
- Join Date
- Mar 2007
- Location
- Redwood City, California
- Posts
- 3,653
- Vote Rating
- 14
In updateListItem, I believe you have a slight problem. I have updated the variables to make it a bit clearer and fixed the logic:
Code:updateListItem: function(record, item) { var me = this, dataview = me.dataview, extItem = Ext.fly(item), innerItem = extItem.down(me.labelClsCache, true), data = record.data, disclosureProperty = dataview.getDisclosureProperty(), hasDisclosureProperty = data && data.hasOwnProperty(disclosureProperty), iconSrc = data && data.hasOwnProperty('iconSrc'), disclosureEl, iconEl; innerItem.innerHTML = dataview.getItemTpl().apply(data); if (hasDisclosureProperty) { disclosureEl = extItem.down(me.disclosureClsCache); disclosureEl[data[disclosureProperty] === false ? 'removeCls' : 'addCls'](me.hiddenDisplayCache); } if (dataview.getIcon()) { iconEl = extItem.down(me.iconClsCache, true); iconEl.style.backgroundImage = iconSrc ? 'url("' + iconSrc + '")' : ''; } },
-
21 Mar 2012 2:56 AM #5
I just took the code and fixed the issue.
Thanks Jamie, that looks better.
*update*: I just tried the code out and it didn't work. No time to check for the issue, will stay on mine.
Success! Looks like we've fixed this one. According to our records the fix was applied for
TOUCH-2387
in
2.0.


Reply With Quote