Building a Tree Widget in GWT - gwt

I am trying to build a Tree Structure in GWT which gets to be scrollable when the number of items are large, the Tree structure will permanently reside on the WestRegion of my Application DockLayout Panel.
The Main code:
<!-- The west side has a panel with complex dynamic tree list to be implemented -->
<g:west size='14'>
<app:Mainlist ui:field='mainlist'/>
</g:west>
The Mainlist:
<g:VerticalPanel>
<g:ScrollPanel>
<g:HTMLPanel width='100%' >
<div class='{style.contentColumn}'>
<g:Tree ui:field='citytree'>
<g:TreeItem text='Delhi/NCR'/>
</g:Tree>
</div>
</g:HTMLPanel>
</g:ScrollPanel>
</g:VerticalPanel>
</ui:UiBinder>
However I dont see anything in the west region. Can anyone point out what am I doing wrong?
Moreover:
In the corresponding "Mainlist.java" file I cannot say #UiField Tree citytree(Gives Exception) . This seems to be because of the nesting involved. How do I access my Tree instance?
The GWT showcase has Tree built without using UiBinder. Moreover I could not find any sample code to build a Tree structure with UiBinder. Any resources?

After searching and exploring more. I did it. I think theere is no example code online so this post might be helpfull for learners like me.
<ui:with field='res' type='myth.social.zomato.client.Mainlist.Images' />
<ui:style src="resources/GlobalStyles.css">
</ui:style>
<g:Tree ui:field='tree' resources='{res}'>
<g:TreeItem text='Cities' >
<g:TreeItem text='Ahemadabad'/>
<g:TreeItem text='Banglore'/>
<g:TreeItem text='Chennai' />
<g:TreeItem text='Delhi/NCR' />
<g:TreeItem text='Hyderabad' />
<g:TreeItem text='Jaipur' />
<g:TreeItem text='Kolkata'/>
<g:TreeItem text='Mumbai'/>
<g:TreeItem text='Pune' />
</g:TreeItem>
<g:TreeItem text='SalesPerson'>
<g:TreeItem text='Sales1' />
<g:TreeItem text='Sales2' />
</g:TreeItem>
</g:Tree>

Related

Create a popup inside a form

I want to include a popup inside a form. The normal way to do that is to have 2 forms like:
<div class="wrapper" >
<h:form>
<h:panelGroup id="id1" layout="block">
<ui:include src= content1 />
</h:panelGroup>
</h:form>
</div>
<h:form id="modalId">
<ui:include src= popupContent >
</ui:include>
</h:form>
and render with a button inside content1, the form "modalId" that contains the popUp.
I have the popup form in an external component that is included inside "content1". Due to the popup form is inside the other form,it isnt well rendered. How can I fix that? The idea is to use that component that is common for all my xhtml views
The way i was writing my own components was to rely on the existance of the external form. That is, i did not include any form elements inside the component.
If there was a need to reference the outer form element then i would just pass the from id as one of the attributes of the interface. Composite components are really useful for this kind of stuff:
<composite:interface>
<composite:attribute name="formId" type="java.lang.String" />
</composite:interface>
<composite:implementation>
<h:commandButton value="button" action="someaction">
<f:ajax execute="#{cc.attrs.formId}" render="#{cc.attrs.formId}" />
</h:commandButton>
</composite:implementation>
Then you include that in your outer form (assuming 'comp' is your namespace for composite components and 'modal' is the name of the file containing the component):
<h:form id="myForm">
<comp:modal formId="myForm"/>
</h:form>
Go through this tutorial if you are not familiar with them:
http://docs.oracle.com/javaee/6/tutorial/doc/giqzr.html

How to define forms in JSF primefaces with pe:layoutPane

I have a template layout with JSF 2 and primefaces and primefaces extensions layoutPane. The left side has an search area and a structure are. The right side is a details area.
Here a short form of the template:
<html>
<f:view contentType="text/html">
<h:head>
</h:head>
<h:body style="width: 100%; height: 100%;">
<pe:layout id="layoutId">
<pe:layoutPane id="layoutPaneWestId" position="west" size="30%" closable="false" resizeWhileDragging="true">
<pe:layoutPane id="layoutPaneSearchId" position="north" closable="false" resizable="false">
<h:form id="searchForm">
<ui:insert name="search" />
</h:form>
</pe:layoutPane>
<pe:layoutPane id="layoutPaneContentId" position="center">
<h:form id="structureForm">
<ui:insert name="content" />
</h:form>
</pe:layoutPane>
</pe:layoutPane>
<pe:layoutPane id="layoutPaneDetailId" position="center" size="70%" closable="false">
<h:form id="detailsForm">
<ui:insert name="details" />
</h:form>
</pe:layoutPane>
</pe:layout>
</h:body>
Each area has its own form. Now I ask myself what shall I do with the e. g. with a global p:growl. In which form should it be? Nested forms are invalid html as I know.
Another big problem is that when I type something in the search field in searchForm and click on an accordion panel in structureForm, the content of the search field is submitted. Why?
Kind regards
Oli
You should put your global p:growl in another form outside pe:layout.
The second problem could be related to some update invoked from structureForm to searchForm

How to use EL with <ui:repeat var> in id attribute of a JSF component

I have following code:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
However, when I open the page, it errors as follows:
component identifier must not be a zero-length String
But it is properly printed in the <h:outputText>. How is this caused and how can I solve it?
You can use EL in the id attribute of a JSF component, but the EL variable has to be available during view build time, while the JSF component tree is to be built. However, the <ui:repeat> runs during view render time, while the HTML output is to be generated based on JSF component tree. The <ui:repeat var> is not available during view build time and #{class2.name} evaluates to null which totally explains the error you got. That it works in <h:outputText> is because it runs during view render time.
If you replace <ui:repeat> by <c:forEach>, which runs during view build time, then it'll work as you intented. The <c:forEach> will namely generate physically multiple <h:form> components in the JSF component tree which each generate individually their own HTML output (in contrary to <ui:repeat>, wherein the very same <h:form> component is been reused multiple times to generate HTML output).
<c:forEach var="class2" items="#{bean.list}" varStatus="status">
<h:form id="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</c:forEach>
However, I really wonder why you need to do that. There's usually no need to dynamically assign component IDs. JSF will already ensure the uniqueness of the ID. The below example,
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="form">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
will end up in multiple forms with each an unique ID, suffixed with iteration index of the <ui:repeat>. If you actually need to use #{class2.name} for some JavaScript/jQuery purposes (you did nowhere state the concrete functional requirement in the question for which you thought that this would be the right solution, so it's merely guessing), then just wrap it in a plain vanilla HTML element:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<div id="#{class2.name}">
<h:form id="form">
<h:outputText value="#{class2.name}" />
</h:form>
</div>
</ui:repeat>
Or set it as style class of a JSF component, which is also just selectable via a CSS selector:
<ui:repeat var="class2" value="#{bean.list}" varStatus="status">
<h:form id="form" styleClass="#{class2.name}">
<h:outputText value="#{class2.name}" />
</h:form>
</ui:repeat>
See also:
JSTL in JSF2 Facelets... makes sense?

Inconsistent primefaces commandbutton behaviour

Using the following code I get an behaviour that I can't explain.
The autocomplete method works fine to select an object.
It updates the panel below as expected.
But then the two buttons (New Airport, Save Airport) are not firing the backing bean listener.
However if I click on one of the buttons before using the autocomplete to load an object, the listener gets fired.
<h:form id="arptForm">
<p:autoComplete minQueryLength="3"
value="#{airportHandler.theAirportNames}" effect="fade"
completeMethod="#{airportHandler.autoComplete}"
forceSelection="true" converter="airportNamesConverter"
var="airport" itemLabel="#{airport.icaoName}" itemValue="#{airport}"
maxResults="#{airportHandler.maxAutoCompleteResults}">
<f:ajax event="itemSelect"
listener="#{airportHandler.airportChanged}" render="#form" />
<p:column style="width:80%">
<h:outputText
value="#{airport.icaoName} - #{airport.iataName} - #{airport.airportName} (#{airport.cityName})" />
</p:column>
</p:autoComplete>
<p:spacer width="20" height="20" />
<p:commandButton id="newAirport" value="New Airport"
icon="ui-icon-newwin" actionListener="#{airportHandler.newAirport}"
update="#form" />
<p:spacer width="20" height="20" />
<p:commandButton id="saveAirport" value="Save Airport"
icon="ui-icon-newwin" actionListener="#{airportHandler.saveAirport}"/>
<p:separator />
<p:outputPanel id="allArptData">
<p:panel id="airportBasics" header="Airport Basics"
toggleable="true" toggleSpeed="500"
rendered="#{airportHandler.theAirport != null}">
<ui:include src="airportbasics.xhtml" />
</p:panel>
<p:panel id="airportRunways" header="Airport Runways"
toggleable="true" toggleSpeed="500"
rendered="#{airportHandler.theAirport != null}">
<ui:include src="airportrunways.xhtml" />
</p:panel>
</p:outputPanel>
</h:form>
Can you explain what happens ?
Thanks
As you said you should not the nest forms that is not correct. Also when you put everything inside a one main form that means you are mixing the processes while submitting that form. There can be lot's of forms per a page like autocomplete form or profile information form etc.
When you do sth. about autocomplete actually you want to submit things about autocomplete not about other buttons so simply seperate them. That does not mean you should have forms for each component but just seperate your page into main sections.

How to re-render a RichFaces component after a4j link is invoked

Hoping someone can help me with a slight hurdle I've come up against in regards to re-rendering of RichFaces components after an a4j link/button has performed it's action. A simplified version of my problem is as follows:
I have 2 output components displaying a text value which are rendered based on some value in my manager class:
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
I also have 2 a4j links that call some action and then re-render the above outputText components:
<a4j:commandLink ajaxSingle="true" value="Set On" action="#{manager.setOn(true)}" reRender="on,off" />
<a4j:commandLink ajaxSingle="true" value="Set Off" action="#{manager.setOn(false)}" reRender="on,off" />
What I would expect to happen is, when I click the 'Set On' button, the 'ON' outputText component would unhide, and the 'OFF outputText component would show. However, this does not happen.
Does anyone have the answer as to why this is so, and how I go about re-rendering these components after the a4j component action has completed?
Wrap the outputText components in an s:div and re-render that as follows:
<s:div id="myDiv">
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
</s:div>
<a4j:commandLink ajaxSingle="true" value="Set On"
action="#{manager.setOn(true)}" reRender="myDiv" />
<a4j:commandLink ajaxSingle="true" value="Set Off"
action="#{manager.setOn(false)}" reRender="myDiv" />
I agree with Gene but the best way I could find is to surround the content with
<a4j:outputpanel id="whatever_id" />
for example,
<a4j:outputpanel id="myDiv">
<h:outputText id="on" value="ON" rendered="#{manager.isOn}" />
<h:outputText id="off" value="OFF" rendered="#{not manager.isOn}" />
</a4j:outputpanel>
You rerender the parent. It doesn't have to be a Seam tag.
I suppose that your h:outputText elements on and off are not rendered at load time of the page.
RichFaces will not rerender these components later even if the value of rendered changed to true.