I have a JSF 2 application which uses a Richfaces 4 tree control. The tree is set to use the "AJAX" switch type. On each selection an AJAX call is made to the server to update the selection value of the tree's backing bean.
On clicking a node there is a delay between the click and the node appearing as selected. The documentation does state that using this method may cause a slight delay, but I wonder why it doesn't just update the style of the node before issuing the AJAX request, so that the user isn't left wondering if the click has been registered.
I've been trying to figure out a way to update the node on a javascript onclick event, but I don't see an id on the span that I'd have to change. Has anyone else tried something similar? Am I going to have to find the parent div and work down to the second span? Surely there's a better way?
Note that using the "client" switch type is not an option, as we need to be able to query for child nodes dynamically. Building the entire tree in one go is not practical in this instance, so it has to be either "server" or "Ajax".
Answering my own question - and contradicting my "no client switching" stipulation a little bit.
Since we're using RichFaces 4, I'm able to specify that tree node expansion should use ajax (allowing the tree to be populated "lazily"), and selection should be client-side only. However, we still had a requirement to store the current selection state in the tree's backing bean. To do so, I added an a4j:jsfunction to the page ...
<a4j:jsFunction name="onSelection">
<a4j:param name="param1" assignTo="#{treeBean.selectedNodeID}" />
</a4j:jsFunction>
... and called it from the "onmousedown" event on each tree node ...
onmousedown="onSelection('#{node.id}')"
This way the tree updates visually without waiting for the ajax request to complete, and feels a lot snappier to the user.
The only problem with this seems to be that the onmousedown event is fired when clicking on the toggle as well, so expanding a node causes it to be "selected" without updating its style. Unfortunately "onselected" doesn't seem to be implemented in the current milestone build.
Related
So the issue is that I'm getting a runtime error about checkboxes generated inside a file tree needing to be inside a form element. Thing is, it is inside a form element but the form element is wrapped around the tree like so:
<t:Form t:id="form>
<t:Tree t:id="tree" model="model" node="node">
<p:label>
${node.label}
<t:Checkbox value="checkboxNode.selected" />
</p:label>
</t:Tree>
</t:Form>
The root level of nodes generate the checkboxes without issue. However, when I select the plus to expand the tree branch it throws the error for the branch checkboxes. This goes away if I refresh the page and it remembers which branches are expanded. If I go to expand more, then it throws the error again. The same thing happens if I minimize a branch and then expand it again.
I suspect this has to do with how expanding the tree generates its fields using an AJAX call and it not being able to detect the form wrapped on the outside. Two possible work around I've thought of are:
Default the nodes as expanded and disable the minimizing functionality. I lose out on one of the interaction and organization advantages of a file tree doing this though.
Put a form inside the label. This creates a lot of unnecessary extra forms though and I'm not quite sure how to consolidate this into the end goal of creating a list of groups to send emails out to based on the selected labels.
Anyone here have any insight about a better work around for this issue or maybe a way to tell the generated checkboxes to recognize the outer form without needing to reload the page?
Ended up using a different route. The issue I ran into with the checkboxes that was a deal breaker was I couldn't think of a way to tell the booleans on the server side to update based on the client side's checkboxes.
The reason for that was that the booleans were generated based on need instead of being a fixed set on the Java side of the page. Tried a work around by linking unique IDs to the booleans on the server side, but even then I could not determine a way to associate those IDs to the checkboxes on the client side.
So instead I went with eventlinks, which can take a context. I just passed in the generated tree node IDs as a context, which could search for the node in the eventlink and be added to a "selected" list on the server.
As JavaDoc for the Tree component states:
Tree is not a form control component...
Have a look at the source code of AjaxFormLoop and the way it handles AJAX form updates, I believe you need to build a custom component for your needs.
I have a problem that I can't find an elegant solution for. I want to use a NestedTree (or something similar) as a simple menu for my page. Each node links to a Page that shows content that is identified by an ID. To get nice URLs and easy bookmarking I'd like to use BookmarkablePageLinks to link to these pages.
But doing it that way creates a completely new Page each time, thus destroying and recreating the tree, resetting it's state. So with each link click the complete tree collapses and the user has to open it again to choose another link.
I can't find a solution, that satisfies these criteria:
Each tab/window retains a separate state
Opening a new tab copies the state from the tab it's opened from, but is then independent
Easy to use, meaning you don't have to manually set and restore state for each link
It would be okay if the state is not restored when the bookmarked URL is called.
With Wicket 1.4 I was able to use the pageMapName to maintain a map of PageMaps and their menu states in the session. But that functionality got altered substantially with Wicket 1.5 (I'm using 6.8 now).
I would be quite grateful for solutions or tips on how to do this.
But doing it that way creates a completely new Page each time, thus
destroying and recreating the tree, resetting it's state. So with each
link click the complete tree collapses and the user has to open it
again to choose another link.
The tree collapses because its model is being recreated on page load. You are probably keeping the tree's model as a member variable on the page. To get around this issue you should store the tree's model in the session object instead. This way you can retain the state across multiple pages.
You can manage your own pageMaps in Wicket 1.5.x and 6.x. All you need is a little Javascript, see AjaxNewWindowNotifyingBehavior for inspiration.
Then you can keep the expansion state of your tree in your session under pageMap-specific keys.
I'm building a page that has a search box that will populate a grid on the same page. There is also a button the user can select to bring up a "window" (JQuery UI "pop-up" in the same page) that lets the user configure said grid.
These are two separate forms but I don't want what was submitted as part of one to undo the other (so when the user submits to change the grid layout the search needs to re-run as well.
I'd rather not store things in session for this since that brings with it its own issues (search results may be large, shouldn't be saved when the page is re-entered later, etc.).
I've considered doing "one large form" (i.e. surrounding all the inputs) for the entire page that is backed by a form backing bean. I would then use which button is clicked to determine the action to take. There will eventually be other buttons on the page as well to add more functionality. This would be similar to how .NET (non-MVC) handles things.
I'm interested in how others may have solved similar challenges. Are there potential issues with my approach that I'm not seeing? Better ways that work with the framework?
What do you mean with:
but I don't want what was submitted as part of one to undo the other
. Are you referring to posting the form and loading the whole page, which in turn will "reset" the other form?
If that is the case I would still keep one page with two forms and make the posts using Ajax (as you may know jQuery makes this a breeze). Upon receiving a response for either call you will need to update the other form accordingly.
Note that you may still have your forms in two separate views if it helps keeping the code clean and then pull their html with Ajax calls into another view. But my point is that at the end I would still keep both in one page since it sounds like they depend on each other so updating one when the other changes may be easier this way,
Let me know if I misunderstood your question.
I'm new to GWT , and I want to create a tree that every time that a node is opened (the user clicked on "+" next to the node) , the actions calls a service with the node id , and the returned results is the list of sons.
Which Class do I need to extend in order to change the behaviour of the "expand" action?
Also , can this be done via smartgwt? How?
Thanks
See the "dynamiac tree" in http://gwt.google.com/samples/Showcase/Showcase.html#!CwTree (click on "source code" to see the source of the sample.
You might also be interested in http://gwt.google.com/samples/Showcase/Showcase.html#!CwCellTree
CellTrees are a bit more complex (and thus harder to grasp) but they perform much better than Trees.
Let's say I have five or more input computers that can affect whether a single drop down menu is displayed. The issue I am running into is that if the drop down menu is displayed once (thus setting the value in the backing bean through ajax) and the user then changes one of the affecting input components, then the backing bean value of the drop down menu is not getting reset when the drop down goes into hiding using the rendered property. For example:
<h:selectOneMenu id="sampleDropDown" required="false" immediate="true"
onchange="jsUpdateSampleDropDownValue()" value="#{backingBean.value}"
rendered="#{backingBean.shouldShowSampleDropDown}"
actionListener="#{backingBean.listener}" />
I understand that I have options here. I've debated whether I should add a generic ValueChangeListener (apply request values phase) or an EventHandler (render response phase) that would listen in on the values of the other inputs and make a decision on whether to clear the drop down menu value but this certainly is more work then just letting the rendered property make that decision.
We've seen dozens of the same type of issue on the project I'm currently on and I'd really like to hear from the experts on the best practice for handling this type of situation. In case it matters we are using custom ajax (not ajax4jsf) and jsf 1.1. Any help is appreciated.
The solution I came up with is to not try and reset the input component in the backing bean value of the renderered property.
I have a phase listener attached to the single page interface and am essentially passing request parameters in the javascript method (i.e. jsUpdateSampleDropDownValue()) so that business logic data can be loaded in the rendered response phase using the chain of responsibility pattern.
When a request parameter is passed (i.e. RESET_SAMPLE_DROP_DOWN) onchange that matches a corresponding event handler (i.e. ResetSampleDropDownEventHandler), I check a separate "constraint" class (see Hardcore Java book) that validates whether enough data is accumulated before either clearing the binding value or continuing with the request.
This allows the logic to be centralized yet be attached to multiple components. You may be asking why a single JSF ValueChangeListener was not attached to each component which would allow the same re-use. The reason for this is because our business logic takes place in the render response phase after the update model phase so it makes sence that any "reset" type methods occur after any "defaulting" of values.