Add child nodes to a nested list dynamically (Sencha Touch 2) - nested-lists

I wonder if you could help me with a problem. I have a nestedlist with 2 levels. When I tap an item on the third level, I dynamically want to query another store that appends itself as a 3rd lvl child node and let it appear.
This is an example of my nestedList. I actually also catch the id of the item I have tapped and send it to a non Sencha API but I didn't include it to the source.
{
xtype: 'nestedlist',
store: 'PackageGroupStore',
listeners: {
itemtap: function(nestedList, list, index, target, record){
// add PackageProductStore here and make it visible
}
}
I already found this one: http://dev.sencha.com/deploy/touch/examples/nestedlist/
But from my understanding it only dynamically adds detailContainers.
Thanks for reading,
Marv

Related

How to re-insert element with same id into sap.m.Page?

I want to remove all content of a page and insert different content into it with a click of a button.
Unfortunately some of the content is the same and therefore has the same id.
I expected it to not be a problem because I never try to insert the same element twice. I want to remove it before reinserting it again.
But apparently the methods I found: oPage.removeAllContent(); and oPage.destroyContent(); don't actually remove the old content completely because I'm still getting the error that I'm trying to add an element with a duplicate id:
Error: adding element with duplicate id 'text'
How can I remove the old content so that the old ids are actually forgotten and I can reinsert them?
Here's a minimal example (click the Reload button twice and on the second time the error will appear in the console):
https://jsfiddle.net/1Lqc36uh/
Here's the most relevant (I think) part:
let oPage = this.byId(this.detailId);
oPage.removeAllContent();
oPage.destroyContent();
if (bSetText) {
oPage.insertContent(new sap.m.Text(this.textId, {
text: "SetText"
}));
} else {
oPage.insertContent(new sap.m.Text(this.textId, {
text: "Test"
}));
}
Delete the line oPage.removeAllContent();.
The issue is that you're removing the content and then trying to destroy it:
oPage.removeAllContent(); // removes the existing content (without destroying it).
oPage.destroyContent(); // tries to destroy but there is no content!
The ManagedObject method destroyXYZ() relies on the fact that the child controls exist as part of the aggregation in the first place.
Removing the controls by removeAllXYZ() does remove them from the UI and makes them no longer related to the parent, but they're not destroyed and still in the control registry. Hence, the "duplicate ID" error.
The method destroyContent() is sufficient to remove the content from the UI and from the control registry.
Do you really need to give each element an ID? Most things can be done without an ID in UI5. Usually a JSONModel is the better approach to control UI elements.
For example you can make the first element visible and the second invisible (even using the same property in the JSONModel so both elements are automatically toggled).
That being said you can destroy the removed elements themself.
oPage
.removeAllContent()
.forEach(oControl => { oControl.destroy(); });
Edit: You can unaccept this answer, seems like #Boghyon gave a better one.

Unity - How to react to scene picking? How to force select a parent by picking its child in the sceneview

I have the following situation I need an answer to:
I have a parent object with children. These children all have unique meshes. Whenever these children are selected in the SceneView, the parent needs to be selected in stead. The children should never have their inspectors exposed (not even a fraction of a second).
How do I do this?
There are two possible solutions that I have come up with which are not the solution I wish to go for.
First being using [SelectionBase] attribute on the parent object. This work perfectly, but only once. The first time the child is selected, the parent gets selected. However, when I click the child again, it still gets selected.
Second solution was to react on Selecten.onSelectionChanged. This however is too slow. I can set the selection to the parent if a child gets selected, but the child gets exposed for a few frames still.
Is there an instant solution to this which can guarantee me the functionality of SelectionBase, but then every time in stead of only the first time I click it?
Thanks in advance! :)
I have found a way to do exactly what i want. I combine the [SelectionBase] attribute with a piece of code in the editor OnSceneGui.
First add the [SelectionBase] attribute to your class
Second add this code to its editor class
private void OnSceneGUI()
{
HandleUtility.AddDefaultControl(0);
//Get the transform of the component with the selection base attribute
Transform selectionBaseTransform = component.transform;
//Detect mouse events
if (Event.current.type == EventType.MouseDown)
{
//get picked object at mouse position
GameObject pickedObject = HandleUtility.PickGameObject(Event.current.mousePosition, true);
//If selected null or a non child of the component gameobject
if (pickedObject == null || !pickedObject.transform.IsChildOf(selectionBaseTransform))
{
//Set selection to the picked object
Selection.activeObject = pickedObject;
}
}
}
This allows the first pick to select the component. From then on, only when you select non-child objects in the scene, selection will actually change.

NatTable - Display a filtered count

I have a FilterRowHeaderComposite layer where a user can input a filter to filter the displayed rows. I also display a count of the current # of rows that are showing.
I was wondering what the best approach would be to update the displayed row count when someone inputs a filter and the number of rows change. Would it be to capture some particular event, extend the FilterRowHeaderComposite and fire some event, etc?
Thanks!
Update:
This is what I ended up doing after Dirks comment
nattable.addLayerListener(event -> {
if (event instanceof RowStructuralRefreshEvent) {
// Code to update count to user
}
});
The GlazedListsEventLayer fires either a RowStructuralRefreshEvent or a VisualRefreshEvent in the UI thread the NatTable stack upwards if a list change occurs. So you can listen to that. Or you do this by creating a GlazedLists ListEventListener that you register on the FilterList and listen directly to changes on the list itself.

ag-grid: Using Drag drop to reorder rows within the grid

I need to re-order rows within ag-grid by using drag-drop. The drag drop methods are simple enough but when the drop occurs there seems no easy way to switch the rows locations.
I attempted a
gridOptions.api.removeItems(selectedNode);
to clear the current and then
gridOptions.api.insertItemsAtIndex(2, savedNode);
but the drop event appeared to re-fire preventing that approach. Plus the insertItems (when ran first) falls over in internal ag-grid looping.
I would rather not re-sort the gridRows manually and then reset the gridRow data which would be somewhat clunky. This seems a common request on most grids so i assume it can be done but have just missed the relevant documentation. Thanks for any help..
K have finally got an Angular 2 method working, though currently I have to switch off sorting and filtering on the grid.
This particular example is relying on row selection being enabled (due to how it is finding some records). Grid dragdrop should be disabled (as that drags the grid visually which sucks) Instead use a processRowPostCreate to set up draggable params at the row level. This sets the dragged option to the row which looks much nicer.
in gridOptions
processRowPostCreate: (params) => {
this.generateRowEvents(params);
},
which calls
private generateRowEvents(params) {
params.eRow.draggable = true;
params.eRow.ondragstart = this.onDrag(event);
params.eRow.ondragover = this.onDragOver(event);
params.eRow.ondrop = this.onDrop(event);
}
I track the source recrord in the onDrag method
var targetRowId: any = $event.target.attributes.row.value;
this.savedDragSourceData = targetRowId;
onDragOver as usual
On drop we have to protect against an infinite loop (ag-grid appears to recall live methods when items are added to the grid hence the ondrop occurs multiple times) and then insert, delete and splice over both the grid and its data source ( I will carry on looking at using the grid to populate the data as opposed to the source data as that would allow source/filter, currently doign that inserts blank rows). An event (in this case) is then emitted to ask the owning component to 'save' the adjusted data.
private onDrop($event) {
if ($event && !this.infiniteLoopCheck) {
if ($event.dataTransfer) {
if (this.enableInternalDragDrop) {
this.infiniteLoopCheck= true;
var draggedRows: any = this.gridRows[this.savedDragSourceData];
// get the destination row
var targetRowId: any = $event.target.offsetParent.attributes.row.value;
// remove from the current location
this.gridOptions.api.removeItems(this.gridOptions.api.getSelectedNodes());
// remove from source Data
this.gridRows.splice(this.savedDragSourceData, 1);
if (draggedRows) {
// insert into specified drop location
this.gridOptions.api.insertItemsAtIndex(targetRowId, [draggedRows]);
// re-add rows to source data..
this.gridRows.splice(targetRowId, 0, checkAdd);
this.saveRequestEvent.emit(this.gridRows);// shout out that a save is needed }
this.v= false;
}
else {
this.onDropEvent.emit($event);
}
}
}
}
NOTE we are wrapping the grid in our own class to allow us to write one set of grid methods and not replicate over the application whenever the grid is used.
I will be refining this over the next few days but as a basic this allows the ag-grid in angular 2 to drag drop rows to sort records.
If you don't find a solution within ag-grid then you can do this by adding one more directive("ngDraggable") and integrate it with ag-grid.
Please find the following working plnkr for this.
https://embed.plnkr.co/qLy0EX/
ngDraggable
Hope this helps..

how to hide and unhide authoerable tabs depending upon value selected from a drop down in CQ5

i am trying to create a footer component in CQ5, where i have 4 columns & all are autherable.
But we have to make no of columns autherable too i.e based on a value selected form a dropdown we have to open those many tabs for authoring those many columns only.
i have created a dropdown and have a maximum range of 6 columns. i know that i have to configure a listener for this purpose but don't know how . Requirement is like if i select 3 from the drop down then 3 tabs should come to author 3 columns
pls help me , i am middle of something very important.i need the solution very early too as i have to finish the job as soon as possible
I might be late for this by now but in case you still need it:
You need to add a listener node before closing your drop-down element:
<listeners
jcr:primaryType="nt:unstructured"
loadcontent="function(box){ //here you also need to handle the hide/unhide when the panel loads for the first time. Use this.getValue() to retrive the intial value }"
selectionchanged="function(box, value) {
for(var c=1;c<=value;c++){
this.findParentByType('tabpanel').unhideTabStripItem("tab"+c); // You need to handle the opposite with hideTabStripItem("tab"+c);
}
}"/>
Then on both "loadcontent" and "selectionchange" (these are events on your drop-down) grab the current selected value and use it to hide/unhide the tabs. In this case the tabs would be named "tab1", "tab2", etc, make sure you get the names right.
The ExtJS in the events is finding the "tabpanel" container for the whole dialog, and then hiding/unhiding based on name. You could also set to enable/disable using the methods ".enable()" and ".setDisabled(true)". Just make sure you get the reference to the tab first if you want to do this (something like ".getComponent(tabName).enable()").
I didn't test this specific code, I couldn't find my actual example from my code base but this should take you in the right direction.