Hi, I'm using an extendet wicket tree with an own tree model. I want to insert child into the tree and want to update the tree with Ajax, but nothing worked for me. I tried invalidateAll() and updateTree(). What can i do to insert the childs with Ajax?
Kai /* ************************************* * code snippet: create and setup tree ************************************ */ TreeModel treeModel = null; HwSubCategoryEnvironmentTree root = hwSubCategoryEnvironmentTreeSer vice.loadPathToRoot(this.hwSubCategoryEnvironmentTree).get(0); if (root != null) { NestedSetNodeWrapper<HwSubCategoryEnvironmentTree> node = hwSubCategoryEnvironmentTreeService.loadSubtree(root); treeModel = node.convertToTreeModel(); } tree = new IconTree("hwSubCategoryEnvironmentTree", treeModel) { private static final long serialVersionUID = -4004667936606595008L; protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) { ... } }; tree.setRootLess(false); ResourceReference icon = new ResourceReference(IconTree.class, "square_orange.png"); tree.setFolderClosedResource(icon); tree.setFolderOpenResource(icon); tree.setItemResource(new ResourceReference(IconTree.class, "square_orange.png")); selectNode(this.hwSubCategoryEnvironmentTree); tree.setOutputMarkupId(true); // add tree add(tree); /* ************************************* * code snippet: update tree ************************************ */ AjaxSubmitLink saveButton = new AjaxSubmitLink("saveRootButton"){ ... protected void onSubmit(AjaxRequestTarget target, Form form) { ... hwSubCategoryEnvironmentTreeService.save(hwSubCategoryEnvironmentTree); tree.invalidateAll(); target.addComponent(tree); } } /* ************************************* * IconTree class ************************************ */ package com.nsn.forlabs.front.components; import java.io.Serializable; import java.util.Comparator; import java.util.Enumeration; import java.util.Iterator; import java.util.NoSuchElementException; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; import org.apache.wicket.Component; import org.apache.wicket.ResourceReference; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.behavior.AbstractBehavior; import org.apache.wicket.extensions.markup.html.tree.Tree; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.tree.ITreeStateListener; import org.apache.wicket.model.IModel; import org.apache.wicket.util.lang.PropertyResolver; /** * Subclass of [EMAIL PROTECTED] wicket.extensions.markup.html.tree.Tree} * <ol> * <li>to tweak its appearance</li> * <li>to allow for easy setting and retrieval of selected nodes</li> * <li>to override a TooltipExtractor</li> * <li>to provide for event callbacks on changes to the tree</li> * </ol> * @author Marco Holmer */ @SuppressWarnings("deprecation") public class IconTree extends Tree implements Serializable { private static final long serialVersionUID = 0L; /** Reference to the icon of open tree folder */ private static final ResourceReference FOLDER_OPEN = new ResourceReference( IconTree.class, "res/node-open.gif"); /** Reference to the icon of closed tree folder */ private static final ResourceReference FOLDER_CLOSED = new ResourceReference( IconTree.class, "res/node-closed.gif"); /** Reference to the icon of tree item (not a folder) */ private static final ResourceReference ITEM = new ResourceReference( IconTree.class, "res/item.gif"); private TreeStateCallback treeStateCallback; private static final Comparator NODE_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { return (o1.equals(o2))? 0 : 1; } }; private static final TooltipExtractor TOOLTIP_EXTRACTOR = new DefaultTooltipExtractor(); private ResourceReference itemResource = ITEM; private ResourceReference folderClosedResource = FOLDER_CLOSED; private ResourceReference folderOpenResource = FOLDER_OPEN; private boolean showIcons = true; private TooltipExtractor tooltipExtractor = TOOLTIP_EXTRACTOR; /** * Tree constructor. * @param id The component id */ public IconTree(String id) { super(id); init(); } /** * Tree constructor. * @param id The component id * @param model The tree model */ public IconTree(String id, IModel model) { super(id, model); init(); } /** * Tree constructor. * @param id The component id * @param treeModel The tree model */ public IconTree(String id, TreeModel treeModel) { super(id, treeModel); init(); } private void init() { //getTreeState().addTreeStateListener(new TreeStateListenerToTreeStateEventConverter()); } protected void populateTreeItem(WebMarkupContainer item, int level) { super.populateTreeItem(item, level); final TreeNode node = (TreeNode)item.getModelObject(); Iterator iterator = item.iterator(); Component component = null; while (iterator.hasNext()) { component = (Component)iterator.next(); if (component instanceof Link && component.getId().equals("nodeLink")) { component.add(new AbstractBehavior() { private static final long serialVersionUID = 1L; public void onComponentTag(Component component, ComponentTag tag) { super.onComponentTag(component, tag); String tooltip = getTooltipText(node); if (tooltip != null && tooltip.trim().length() > 0) { tag.put("title", tooltip); tag.put("showtooltip", "true"); } } }); } } } /** * Sets the enabeled state of all sub components. * @param enabled */ @SuppressWarnings("unchecked") public void setChildrenEnabledState(final boolean enabled) { this.visitChildren(new IVisitor() { public Object component(Component component) { component.setEnabled(enabled); return component; } }); } /** * Extracts the tooltip text for a given node. If the node is an instance of * DefaultMutableTreeNode, the nodes user object is extracted and the given * tooltipExtractor callback is called. * @param node the given tree node * @param tooltipExtractor a supplied TooltipExtractor implementation for customization. * @return a tooltip or an empty string. */ protected String getTooltipText(TreeNode node) { if (node instanceof DefaultMutableTreeNode) { Object obj = ((DefaultMutableTreeNode)node).getUserObject(); return getTooltipExtractor().getTooltip(obj); } return ""; } /** * Returns the currently set TooltipExtractor implementation. * The default implementation returns a TooltipExtractor that tries to find a description property. * A callback pattern is not applicable here as the TooltipExtractor ist already needed in the constructor. * @return the [EMAIL PROTECTED] TooltipExtractor} to use. */ public TooltipExtractor getTooltipExtractor() { return tooltipExtractor; } public void setTooltipExtractor(TooltipExtractor tooltipExtractor) { this.tooltipExtractor = tooltipExtractor; } /** * Selects a node based on a Comparator implementation. All nodes of the tree are searched until the given * Comparator yields '0' (that is zero). The search is stopped and the node selected. * @param nodeObjToSelect the given object to search the tree for (user object of a DefaultMutableTreeNode) * @param comparator the comparator to use for the search */ @SuppressWarnings("unchecked") public void selectNode(Object nodeObjToSelect, Comparator comparator) { Object modelObj = this.getModel().getObject(); if (modelObj instanceof TreeModel) { TreeModel treeModel = (TreeModel)modelObj; if (treeModel.getRoot() instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode root = (DefaultMutableTreeNode)treeModel.getRoot(); Enumeration allNodes = root.depthFirstEnumeration(); DefaultMutableTreeNode node; Object obj; while(allNodes.hasMoreElements()) { obj = allNodes.nextElement(); if (obj instanceof DefaultMutableTreeNode) { node = (DefaultMutableTreeNode)obj; if (comparator.compare(nodeObjToSelect, node.getUserObject()) == 0) { this.getTreeState().selectNode(node, true); return; } } } } } } /** * Selects a node with a user object that equals the given object. * The default implementation compares using the equals implementation. * @param selectedObj */ public void selectNode(Object selectedObj) { selectNode(selectedObj, NODE_COMPARATOR); } /** * Helper method that returns the selected DefaultMutableTreeNode. */ public DefaultMutableTreeNode getSelectedNode() { Object selected = null; try { selected = this.getTreeState().getSelectedNodes().iterator().next(); } catch (NoSuchElementException nseEx) { } return (selected instanceof DefaultMutableTreeNode)? (DefaultMutableTreeNode)selected : null; } public void setShowIcons(boolean showIcons) { this.showIcons = showIcons; } public boolean getShowIcons() { return showIcons; } protected ResourceReference getItem() { return itemResource; } public void setItemResource(ResourceReference res) { this.itemResource = res; } protected ResourceReference getFolderClosed() { return folderClosedResource; } public void setFolderClosedResource(ResourceReference res) { this.folderClosedResource = res; } protected ResourceReference getFolderOpen() { return folderOpenResource; } public void setFolderOpenResource(ResourceReference res) { this.folderOpenResource = res; } /** * For simplicity there is no listener approach but rather a single callback implementation. */ public void setTreeStateCallback(TreeStateCallback callback) { this.treeStateCallback = callback; } protected void fireTreeEvent(TreeStateEvent event) { if (treeStateCallback != null) treeStateCallback.onTreeStateEvent(event); } /** * A callback interface to generate tooltip texts for the user object of tree nodes. */ public interface TooltipExtractor { String getTooltip(Object obj); } /** * A default implementation of of the TooltipExtractor interface that tries to * extract the tooltip text from a description property of the underlying object. */ public static class DefaultTooltipExtractor implements TooltipExtractor, Serializable { private static final long serialVersionUID = 0L; public String getTooltip(Object obj) { Object description = null; try { description = PropertyResolver.getValue("description", obj); } catch (Throwable t) { } return (description != null)? description.toString() : ""; } } /** * Implement to get notified of TreeStateEvents. */ public interface TreeStateCallback extends Serializable { public void onTreeStateEvent(TreeStateEvent event); } /** * Differentiates the TreeStateEvents with a certain type. */ public enum TreeStateEventType { ALL_NODES_COLLAPSED, ALL_NODES_EXPANDED, NODE_COLLAPSE, NODE_EXPAND, NODE_SELECT, NODE_UNSELECT } /** * TreeStateEvents are generated on any change to the underlying tree model of the IconTree. */ public class TreeStateEvent implements Serializable { private static final long serialVersionUID = 0L; TreeStateEventType event; TreeNode node; public TreeStateEvent(TreeStateEventType event, TreeNode node) { this.event = event; this.node = node; } } /** * Execute some javascript in case of AJAX links that fixes the mess left behind by the DOM changes. */ @Override protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) { if (target != null) { target.appendJavascript("sweetTitles.tipOut(); sweetTitles.init();"); } } /** * Dispatch TreeState changes to a simpler callback event ([EMAIL PROTECTED] TreeStateEvent}). */ private class TreeStateListenerToTreeStateEventConverter implements ITreeStateListener, Serializable { private static final long serialVersionUID = 0L; public void allNodesCollapsed() { fireTreeEvent(new TreeStateEvent(TreeStateEventType.ALL_NODES_COLLAPSED, null)); } public void allNodesExpanded() { fireTreeEvent(new TreeStateEvent(TreeStateEventType.ALL_NODES_EXPANDED, null)); } public void nodeCollapsed(TreeNode node) { fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_COLLAPSE, node)); } public void nodeExpanded(TreeNode node) { fireTreeEvent(new TreeStateEvent(TreeStateEventType.ALL_NODES_EXPANDED, node)); } public void nodeSelected(TreeNode node) { fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_SELECT, node)); } public void nodeUnselected(TreeNode node) { fireTreeEvent(new TreeStateEvent(TreeStateEventType.NODE_UNSELECT, node)); } } }