Unable to update item in tree!

Hi,

Trees and containers are more like a nightmare to me!

I keep struggling with the Container and Tree concepts!

I’ve a container defined like:

public void fillEntryTree(TargetGroup group) { container.addContainerProperty("myid", String.class, null); container.addItem(group); if (group.getEntries().isEmpty()) { container.setChildrenAllowed(group, false); } else { for (int i=0; i<group.getEntries().size(); i++) { Entry entry = (Entry) (group.getEntries().get(i)); container.addItem(entry); container.setParent(entry, group); if (entry.getSubEntries().isEmpty()) { container.setChildrenAllowed(entry, false); } else { // In case more subentries are available! } } } tree.setContainerDataSource(container); } The container is defined as:

private HierarchicalContainer container = new HierarchicalContainer(); Now the container holds my Entry objects, and displays them correctly in the tree.

When I use the command:

currentItem.getItemProperty("myid").getValue();

I get the correct response!

However when I want to update the Entry using:

container.getContainerProperty(currentItem, "myid").setValue("9090"); I get a null pointer exception, and don’t understand why!?

What’s wrong here? Any suggestions are more than welcome! Thanks in advance.

Gerard

Hi,

Note that

container.getContainerProperty(currentItem, "myid").setValue("9090" takes an itemId as first argument, NOT an item as it looks like you are trying. The itemId in your code is the parameter you use when adding the entry:

 container.addItem(entry); // entry will be your itemId

Hope this helps (I haven’t verified, so please test) :slight_smile:

Hi,

Thanks for your response, but unfortunately that doesn’t seem to help!

What I tried immediately after adding the items; I inserted the following print statement:

System.out.println(container.getItem(entry)); which yields all null values!!!

That’s something I don’t understand at all. Also the data model with properties, items and containers in relation to trees isn’t clear to me, sorry! Neither can I find a clear explanation of this subject, on the Internet. The part of the Vaadin book dealing with this topic, I tried that too, but it isn’t to much of help to me, sorry!

Currently, I’m completely stuck!

Regards,
Gerard

Hm and

container.addItem(entry);

Does not return null either? Have you checked that there is no struggle with strangely overridden equals()/hashcode() methods for Entry?

Your items are not probably null, but the representation yields null for them.
Instead of doing

System.out.println(container.getItem(entry));

Try

System.out.println(container.getItem(entry).getItemProperty("myid");

As how you should think about containers in vaadin: For every row, there is an item ID that points to the item(row). To pinpoint the correct property of that item, you also need a property ID. It is kind of a coordinate system, but instead of x and y, you have propertyId and itemId.

Hi,

The addItem doesn’t return null!

The Entry class is only overriding the toString() method!

Well, I’ve added this statement to the fillEntryTree method:
tree.getItem(entry).getItemProperty("myid").setValue(entry.toString()) The Entry selected from the tree is displayed in a pane adjacent to the tree pane, on the same page. The pane displaying the Entry holds an Edit button. When this Edit button is pressed a modal window pops-up enabling the user to modify the Entry. When clicking the OK button of the modal edit window, the pane displaying the Entry updates correctly, but the Entry in the tree isn’t!

Regards,
Gerard

Hi,

Well, that’s indeed what I grasp from all the description so far, but what has this to do with trees?

I’ve a tree of Entries with certain characteristics. Each Entry has a unique name that is used to show the Entry in the tree.

So I don’t understand how this data model comes in, sorry!

Regards,
Gerard

Hello again!

I’m not 100% sure that I’m following your thoughts, but if you edit the underlying Entry and want to get the change reflected in the tree, I would suggest doing something like the following (just as an example):

First, let’s assume you have some kind of Entry with some kind of characteristics:

[code]
private class Entry {

    private String displayable;

    private String nonDisplayable;

    public Entry(String disp, String nonDisp) {
        setDisplayable(disp);
        setNonDisplayable(nonDisp);
    }

    @Override
    public String toString() {
        return displayable;
    }

    public String getDisplayable() {
        return displayable;
    }

    public String getNonDisplayable() {
        return nonDisplayable;
    }

    public void setDisplayable(String displayable) {
        this.displayable = displayable;
    }

    public void setNonDisplayable(String nonDisplayable) {
        this.nonDisplayable = nonDisplayable;
    }

}

[/code]Then, let’s create the tree and container (I’ll comment on what is happening, line by line):

        final Tree tree = new Tree("Tree test");
        final HierarchicalContainer hc = new HierarchicalContainer();

        // Instead of a String, let's use the Entry to be editable instead
        hc.addContainerProperty("entry", Entry.class, null);
        hc.addContainerProperty("somethingElseIfYouWant", String.class, null);

        // We add a few entries with some characteristics:
        final Entry e1 = new Entry("e1 to show", "e1 NEVER");
        // e1 functions as the itemId, (but actually I would myself use something else for identifying the items, like a String)
        hc.addItem(e1);

        Entry e2 = new Entry("e2 to show", "e2 NEVER");
        hc.addItem(e2);
       
        /* First we get the item, using the item identifier, and then getting the property
         * using the propertyId "entry". Here your Entries will reside as defined earlier
         * in the container */
        hc.getItem(e1).getItemProperty("entry").setValue(e1);
        hc.getItem(e2).getItemProperty("entry").setValue(e2);

        tree.setContainerDataSource(hc);

        // These two lines will pick up the toString() from entry as the caption for the items in the tree
        tree.setItemCaptionMode(ItemCaptionMode.PROPERTY);
        tree.setItemCaptionPropertyId("entry");
        someLayout.addComponent(tree);

        // Next I'll create a button with a click listener that edits the selected item in the tree:
        Button b = new Button("Edit selected item");
        b.addClickListener(new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                // The value (selected item) is an item Id (Entry in our case)
                Object itemIdWhichIsAnEntry = tree.getValue();
                if (itemIdWhichIsAnEntry == null) {
                    return; // In case of no selection in the tree
                }

                /* Here get the item (using the itemId), then get the value for the property for that item
                 * and cast it to an Entry (make sure there are no null values). Now we can modify our Entry
                 */
                ((Entry) tree.getItem(itemIdWhichIsAnEntry)
                        .getItemProperty("entry").getValue())
                        .setDisplayable("Changed the entry");
                /* Since we edit our Entry externally, the container/tree does not make note of that.
                 * This means that we have to make the tree dirty in order to be repainted */
                tree.markAsDirty();
                // tree.set

            }
        });
        someLayout.addComponent(b);

The HierarchicalContainer extends IndexedContainer actually. It can be used as both, which means that the same rules also applies to HC.

Hi Johan,

Thanks for the example with the added comments! That is really helpful!

Regards,
Gerard