Checkboxes Inside A File Tree - java

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.

Related

XPages: losing variables in partially refreshed custom controls

I could do with some help once again...
We built our own forms in XPages. Forms are defined by a user in Notes, and they are used through XPages/web. We added several managed beans to get more grip on the data used by the page and controls that are on it. The whole thing is heavily nested, the form control can be used more than once on a page, repeat controls are used as well, and now I need to partially refresh a panel.
Some of the code:
<xp:panel id="ccAnyForm">
<xp:this.dataContexts>
<xp:dataContext var="formulaire">
<xp:this.value><![CDATA[#{javascript:compositeData.formName || compositeData.dataSource.getItemValueString("Formulaire")}]]></xp:this.value>
</xp:dataContext>
<xp:dataContext var="formdata">
<xp:this.value><![CDATA[#{javascript:PageData.getForm(formulaire, compositeData.dataSource)}]]></xp:this.value>
</xp:dataContext>
</xp:this.dataContexts>
<xp:panel id="aFormulaire${javascript:compositeData.name}">
<xe:switchFacet id="switchFacet1">
<xe:this.selectedFacet><![CDATA[#{javascript:formdata.isTabbed()? "tabbed": "flat"}]]></xe:this.selectedFacet>
PageData is a Java bean, and I lose formdata when doing a partial refresh. If I set partial execution mode in the EventHandler (data validation is disabled), I get the error that says formdata not found on the last line of the snippet. If I clear partial execution mode, I get nothing at all: no error, no Java error, no SSJS error, nothing.
It must be my lack of understanding the life-cycle of objects and variables, for I prbably have to use ValueBindings or so, but I don't know how.
Help...
I've seen dataContexts recalculate as null, particularly when dependent on other dataContexts. I think in Apply Request Values phase. When I had that I changed the code to only calculate in Render Response phase.
However, I don't think that work for you, because the Switch control will need the value before Render Response, and there's no easy way to get hold of which other phase is running.
The approach I'd take is to have a property in your bean (e.g. showTabbed) that holds which Switch facet to show. Call a bean method to set that property on page load. Then in your partial refresh, call the method again, checking whether the Formulaire field has changed to determine whether or not to call setShowTabbed(boolean) again. That will minimise the number of calls even more and should prevent the problem.

Retaining the state (collapsed/expanded nodes) of a NestedTree when using BookmarkablePageLink

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.

Spring MVC 3.0 - multiple forms or one?

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.

AJAX delay on richfaces tree selection

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.

ZK grouped listbox performance

I'm currently working on a ZK screen with a Listbox that contains groups. Since you can't (as far as I know) use DataBinder to set the model with a GroupsModel, I'm manually creating one and calling setModel. To configure the Listgroups and Listitems I need to create a ListitemRenderer, which I've done.
The problem is that whenever you open or close a group on the screen, it communicates with the server to set the group as being open, and calls the ListitemRenderer again for every visible row. This results in a laggy interface for the user.
Is it possible to get ZK to cache the contents of the Listgroups and Listitems on the client such that opening/closing groups will not talk to the server and doesn't render every row again? With this system, the contents of the rows will not change until the user performs another search, or if they drag/drop items.
Edit:
I ended up just building the Listgroups and Listitems myself and adding them with appendChild. No need for a model or renderer, so everything is done on the client meaning it's very snappy. It'd still be nice to know how it could be done with a model/renderer though.
I suggest you can use renderall() method.
e,g
myListbox.getItemRenderer().renderAll()
IMO, if your model contains a lot of data, this action will maybe slower than default action.

Categories