I have a nestedList with a few levels that appears when the user presses a button on the screen. When the nestedList appears, there is no back button (because we're at the top of the tree, so understandably there is nowhere to go back to), whereas tapping on items in the list takes you to screens with a back button.
I'd like to add a back button to the first screen. I have managed to do this, but not without adding the same back button to every sublist in the nestedList - this has the effect of 1 back button at the top level, and 2 back buttons (one to take you out of the nestledList completely, and one to take you up a level) at every subsequent level.
Can anyone help me figure out how to have 1 back button on each screen, including the top level to close the list?
Many thanks
PS a nasty workaround that I'm using at the moment is to have a "close" button in the top right of every screen instead.
I don't know how comfortable you are with the inner workings of Sencha Touch so how you go about doing this is up to you--
The back button is there, hidden, when the nested list is shown (created in the initComponent function with hidden: true), and then onBackTap, onItemTap and setActivePath will all call syncToolbar near the end of their functions which is where the back button is hidden when you are at a depth of 0.
So there are 2 places you need to do something about, first is initComponent which is easy-- just implement initComponent in your nestedList, call the superclass' initComponent and then set the backButton visible
var myNestedList = new Ext.NestedList({
...,
initComponent: function() {
myNestedList.superclass.initComponent.call(this);
this.backButton.setVisible(true);
},
...
});
That takes care of showing it intially.. how you care to deal with fixing syncToolbar is up to you. You can use Ext.override, you can straight up copy and paste the whole syncToolbar function into your nestedList object which would also override it or you could do what you're told never to do and just edit the sencha-touch.js file directly. However you decide to do it, what you're looking to change is
syncToolbar: function(card) {
...
backToggleMth = (depth !== 0) ? 'show' : 'hide';
if (backBtn) {
backBtn[backToggleMth]();
if (parentNode) {
backBtn.setText(backBtnText);
}
}
... };
You can either change backToggleMth to = 'show' or just delete the if (backBtn {...} all together.
In the Sencha Touch 2.2 I had to use a different code:
Ext.create('Ext.NestedList', {
...,
listeners: {
initialize: function(obj) {
obj.getBackButton().show();
},
back: function(obj, node, lastActiveList, detailCardActive) {
switch(node.getDepth()) {
case 1:
obj.getBackButton().show();
break;
case 0:
alert("wohooooooo!");
break;
}
}
}
}
Related
I have created a component that allows users to select objects from a list and put them into another "selected list" lets say. So there are 100 items in the main list and however many in the users selected list. They can of course remove and add items as they want.
There are two buttons at the bottom of the modal. Cancel and Update. Where Cancel forgets anything they have added or removed (essentially an Undo of when they popped up the modal) and Update technically does nothing because when you are adding and removing, I am actually updating the real selected list.
So my data has these two properties (among others of course):
originalSelections: [],
selectedMedications: [],
There is a method that only gets called one time to set the selectedMedications property to whatever the current state of originalSelections is. I have a console.log to prove I am not running this method more than once and it NEVER gets hit again.
console.log('Post Initing');
let Selected = [];
for (let med of this.value.OtherNotFromEpic) {
let match = this.otherMedications.find(x => { return x.value === med });
if (match) {
Selected.push(JSON.parse(JSON.stringify(match)));
this.originalSelections.push(JSON.parse(JSON.stringify(match)));
this.selectedMedications.push(JSON.parse(JSON.stringify(match)));
}
}
I was baffled at why the selectedMedications was changing, so I added a watch to let me know if it was:
watch: {
originalSelections(newValue) {
console.log(' ** Original Selection Changed', this.init, newValue);
},
},
The Cancel method is as follows:
cancel() {
$('#' + this.modalID).modal('hide');
console.log('Cancel: this.originalSelections', JSON.parse(JSON.stringify(this.originalSelections)));
this.selectedMedications = this.originalSelections;
this.$nextTick(() => {
console.log(' Cancelled: this.selectedMedications', JSON.parse(JSON.stringify(this.selectedMedications)));
});
},
You can see that I am setting selectedMedications to whatever it was originally.
The odd thing is... This WORKS 100% the first time I bring up the modal. So I pop up the modal, remove an item, cancel the modal and it brings back the item I removed. Perfect!
If I bring the modal up again, remove that same item or any other item, cancel the modal and that item stays removed and the watch is actually hit. I have NO other place in the code where originalMedications = … or originalMedications.push or even originalMedications.slice ever happen. And it is my understand that the JSON.parse(JSON.stringify(match)) code I use to set it is making a new object and not a reference in any way.
Another odd thing I have found is that if I refresh the page, open the modal, cancel out without doing any adding or removing. Then I bring up the modal again and try either add or remove, then cancel the modal, those items do not revert back to the originalMedications state because originalMedications is the same as selectedMedications. Aargh!
So HOW can a property get altered when I never do anything to it after the initial setting of it?
In the cancel method, when below direct assignment is done here after both data is referring to same (since its array). So any time after the first cancel both originalSelections and selectedMedications array would have same reference and hence same data.
this.selectedMedications = this.originalSelections;
instead better to use concat as below? This will create a copy of originalSelections and assign that to selectedMedications. So any operations on selectedMedications will not affect the originalSelections.
this.selectedMedications = [].concat(this.originalSelections);
I'd like to be able to hide and show certain buttons in a navigation view bar when a view is push and popped onto the view stack. Shame I can't control that from the view config itself (but I'll save that moan for another time).
I wanted to know which events I should be using when a view is push/popped on a navigation view. The docs sometimes lie and I've been told many times not too trust it, so I'm not! Come on Sencha, Microsoft wouldn't get away with this!
So Any ideas? When I try to print out all the events for a view I get very unreliable behaviour:
What I've found:
When I push a view I get:
initialize
hide
show
When I pop a view I get:
hide
show
What the flip is going on?!?
The code to show events happening:
control: {
myViewRef: {
initialize: function() { console.log("initialize") },
activated: function() { console.log("activated") },
deactivated: function() { console.log("deactivated") },
painted: function() { console.log("painted") },
show: function() { console.log("show") },
hide: function() { console.log("hide") }
},
}
The code to actually push/pop a view:
onInBoxListViewItemTap: function(scope, index, item, record) {
console.log("onInBoxListViewItemTap");
var detailsView = this.getEnquiryDetailsViewRef();
// push view
var navview = this.getMyInboxViewRef();
navview.push(detailsView);
}
Does this stuff actually work properly i.e. Are there concrete events which are guaranteed to fire when a view is pushed and popped?
First of all - you have a typo in your code. You need to reference activate and deactivate not activate_d and deactivate_d.
Second, I would try to subscribe to push and pop events of navigation view and see if it would get you what you want.
I have the same problem.I use painted handler to solve it.
You can't handle 'painted' event in controller
the painted event description
I would like to create an event listener to detect when my nestedlist is at the top level, and then hide a component on the page. For example:
onNestedlistActiveItemChange: function(container, value, oldValue, options) {
if (this.getMyNestedList().atLevel(0)) <-- seudo code, does not work
{
Ext.getCmp('myButton').hide();
}
}
Thanks in advance for your help
The _backButton._hidden property of the nested list will return true when the default back button is hidden and false when the button is displayed. The button is hidden only when the nested list is at the top level.
The trick is to use the nested list's "back" event, which returns the state of the toolbar after the back event has occurred:
onMynestedlistBack: function(nestedlist, node, lastActiveList, detailCardActive, options){
if(nestedlist._backButton._hidden) {
Ext.ComponentQuery.query('#myButton')[0].hide();
}
}
That is, if the nested list's back button is hidden, then the list is at the top level, so hide myButton.
There are certainly more rigorous ways to do it, but most of them would involve overriding the toolbar's default button handling.
You can get the list level by checking the index of the list
var idx = nestedlist.getInnerItems().indexOf(list);
if (idx === 0) {
// top level...
}
[UPDATE]
You can also check the depth level of the record
var depth = record.getData().depth;
if (depth === 1) {
// top level...
}
I have an ExtJS 4 grid with GroupingSummary Feature. ExtJs Default is grid is expanded when user clicks on any cell in grouping row. I want to disable this feature, no expansion should take place except when user clicks on designated 'expand' icon. How do I accomplish this?
There is the 'groupclick' event, is there a way to override its default behaviour and do nothing / remove it?
Thanks in advance
The method for it appears to be inherited from Grouping rather than GroupingSummary, so I suspect you need to override this method to prevent the current behaviour:
onGroupClick: function(view, group, idx, foo, e) {
var me = this,
toggleCls = me.toggleCls,
groupBd = Ext.fly(group.nextSibling, '_grouping');
if (groupBd.hasCls(me.collapsedCls)) {
me.expand(groupBd);
} else {
me.collapse(groupBd);
}
So you will need another file with something similar to the following:
Ext.require('Ext.grid.Grouping');
Ext.define('your.class.here', {
override: 'Ext.grid.Grouping',
onGroupClick: function() {
//do nothing
});
)};
Then you should be able to write a function that mimicks it was doing on groupclick, but instead on your icon click. Hope that helps.
I have a tabpanel with items of nestedlists. Each nested list goes several levels deep. If I drill down one of the nested list, then i click on a different item in the tabpanel, then click back to it, the nested list is still drilled down, instead of refreshing to the top level of the nested list.
How do I get the nestedlist to display the top level instead of the drilled down level everytime I return to it?
Additional Info
OK, I'm part way there. Here's the code I have now:
var tabBar = new Ext.TabPanel({
fullscreen: true,
id : 'footer',
cardSwitchAnimation:false,
listeners: {
cardswitch: {
fn: function() {
Ext.getCmp('footer').getActiveItem().setActiveItem(0);
}
}
},
tabBar: {
dock: 'bottom'
},
items: [/* some nestedlist components */]
});
So the final problem is that everytime I cardswitch, I see the "drillup/slideback" animation of the nested list sliding back or drilling back to the top level item. How do I get it to just show the top level item without this drill up/slide back animation? I want to preserve the slide forward and drill down animation when the user drills down the nestedlist.
You can try to set the cardSwitchAnimation parameter to false in the setActiveItem method
[UPDATE] Deselect item
Add an event listener for the item tap event on the nested list
nestedList.on("itemtap", function(nestedlist, index, item, e){setTimeout(function(){nestedlist(index);},500);}, this);
[UPDATE] From John
For some reason your code didn't do anything for me. But this one worked:
var nestedList = new Ext.NestedList({
store: store,
listeners: {
itemtap: function(dv, ix, item, e) {
// Clear the selection soon
setTimeout(function(){dv.deselect(ix);},500);
}
}
});
In March 2014, with version 2.3.1, I had the above problem with the Ext.dataview.NestedList object. The suggested approach of using the "deselect" method did not work for me - probably because of the two years that have gone by since the original question.
To resolve problem, I used the following:
nestedList.goToNode( nestedList.getStore().getRoot() );