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

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.

Related

Add row to start of Dgrid instead of end using Rest call

As you know, dgrid 0.4 now uses the dstore package instead of dojo's store. Using the Rest.js in dstore, I simply want to add a new row to the dgrid using a rest call. This works fine. However, it adds the row at the end (as the last row) of the dgrid. I need to add the row at the beginning (making the newly added row the first row of the dgrid). Inside Rest.js, there is a variable called defaultNewToStart which I figured would do the trick, but even when set to true, dgrid still adds the row at the end. Any advice on how to get Rest.js in dstore to add a row to the beginning of the dgrid.
I figured out what I did wrong. In dgrid/OnDemandGrid, I set the property "sort", which was causing the queryExecutor in Trackable.js to put the newly added row at the end instead of the beginning. So all I had to do was remove the sort property, and now it works fine.
The add function of dstore/Memory supports PutDirectives as second argument other than the item you are trying to insert. PutDirectives has a property beforeId which can be used to insert the item before any existing record in store.
To add an empty row at the beginning:
var beforeID = null;
store.fetch().forEach(lang.hitch(this, function(data) { beforeId = data.id;}));
store.add({id: ''}, {beforeId: beforeID});

MvvmCross DataBinding To Modify Individual Item in Android ListView

I am trying to dynamically modify the items in a List (ObservableCollection) of a ViewModel and have those changes get updated in the View via MvvmCross bindings. My eventual goal is that when a user clicks on a list item, I will pop up a dialog asking them to edit that item. When the dialog is dimissed, the viewmodel will get updated (through an ICommand I assume) and that modified value will be now be in the list.
I haven't looked into dialogs yet, so for now I am just trying to toggle a boolean value each time a list item is clicked and have that value changed in the MvxListView. I have the MxvListView in my View bound to an ObservableCollection in my ViewModel and have an MvxCommand that is getting called when an item is selected. All this is working and I can see the value getting changed in the debugger, however, the new values are not being displayed in the MvxListView. So my question is: How do I get modified data in individual items in an ObservableCollection to bind to an MvxListView?
All of the examples I have seen online use ObservableCollection for dynamic binding but they only ever Add or Delete items. I haven't found any examples of modifying the items. If I change the code in my MvxCommand from modifying the data to adding or deleting an item, the list will get updated. So that tells me I'm close I think.
Rather than copy paste the code in here, I created a sample project on github here to look at:
https://github.com/smulrich/breaktimer
I appreciate the help.
You can simply replace
Breaks[index] = b;
with
Breaks[index] = new DailyBreak() { Reason = b.Reason, TimeOfDay = b.TimeOfDay, Enabled = b.Enabled };
or more reasonable, you should realize INotifyPropertyChanged for class DailyBreak
Diffrent among List, ObservationCollection and INotifyPropertyChanged, please refer to enter link description here

Unity/NGUI Updating List at runtime

I was wondering if someone could explain to me how I update a list at runtime in Unity?
For example I have a spell book, which has 3 spells in it, when I drag them to my action bar they get re-parented to it, what I'm trying to do is get a list of each child under the actionbar transform,
My problem is where to actually do something like this if I try something like below in the update, it adds whatever's there many times, which I can understand since update runs every frame..
list = actionbarui.GetComponent(UIGrid).GetChildList();
for(var i =0;i < list.size; i++)
{
buttonList.Add(list[i].gameObject);
}
If I add a callback to the buttons so that whenever they're drag and dropped it runs the above code and add thing's additively, as in, if you drag just one "spell" on it will loop through once, which is fine, but as soon as you add another it loops through three times, that is, it already has one it then adds the same one again PLUS the new button that's just been dragged on for a total of 3.
I've tried changing the code to
list = actionbarui.GetComponent(UIGrid).GetChildList();
for each(var child : Transform in list.GetEnumerator())
{
buttonList.Add(child.gameObject);
}
But this simple doesn't add anything, I am unsure how to go about keep the lists update as they are dragged off and on, could anyone please explain how this is achieved?
Please ignore the second "list" code, it's implementing "BetterLists" as apart of NGUI, so doesn't follow standard list methods.
Thank you for reading
If I add a callback to the buttons so that whenever they're drag and dropped it runs the above code and add thing's additively, as in, if you drag just one "spell" on it will loop through once, which is fine, but as soon as you add another it loops through three times, that is, it already has one it then adds the same one again PLUS the new button that's just been dragged on for a total of 3.
That is the expected result here. You are running through the list of children and adding them to your buttonlist, so first time there is only one item to add, then when you add another child there are two items to add, thus resulting in three items.
Either don't have a for loop and do:
buttonList.Add(the_GameObject_that_was_just_added_to_the_bar);
Or clear your buttonList before the for loop:
list = actionbarui.GetComponent(UIGrid).GetChildList();
buttonList.Clear();
for(var i =0;i < list.size; i++)
{
buttonList.Add(list[i].gameObject);
}
Alternatively to Dover8's response, you can first check if the buttonList already contains a reference to the child to be added. If it does, continue. Otherwise add the new child.
However, given the expense of doing the checks, and since you are already looping through the list already, I'd recommend that you follow his suggestion to clear the list before running the loop. It will probably give you the best performance out of these examples.
If there's a reason you can't or shouldn't clear the buttonList, and you still need to run through it, I'd recommend my suggestion. It really depends on which implementation works best for what you are trying to do. The point is that there are several ways to do this, and they have different performance profiles you need to consider.

Wicket's input looses behavior after the form it's in is submitted

I have a form and a series of panels containing inputs inside it, as a list. When I click the add button, the form is submitted and a new item is added into this form. Input inside a newly created panel gets date-picking behavior. The problem is that it cancels behavior applied to inputs which already were on that form (added previously). Inputs in other forms are not affected.
Each field behavior is applied onto has unique name. Values inside inputs are processed correctly.
How to preserve behavior applied on old inputs?
How to preserve behavior applied on old inputs?
You probably put your input fields into a ListView, right? If so, try calling ListView.setReuseItems(true). This setting makes sure that when you add something to the listview and it is rendered again that the old items (with the old input fields and their behaviors) will be kept instead of creating new ones.

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

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