primefaces input with tooltip button - jsf

I would like to create input-field-attached-tooltip-button (I don't quite know what to call it). Something like this:
When you hoover over the question mark icon you see the help text.
Justification: The little icon makes it blatantly obvious that there's help attached to the field. You can see that help is indeed available without even moving the mouse pointer to the field. Gives the user this warm fuzzy feeling.
I cannot figure out how to do this in PrimeFaces.
I do not know which framework has produced the example above but I'm pretty sure it is not PrimeFaces.
I'm well aware of <p:tooltip> but I don't think it can do this.

So here's what I've come up with in PrimeFaces:
(my screencapture does not show the mouse pointer)
I pretty much took BalusC's suggestions and created a JSF custom component. Here's what my custom component look like:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="helptext"/>
<composite:attribute name="show" />
</composite:interface>
<composite:implementation>
<p:button id="help" style="width: 15px; height: 15px" icon="ui-icon-help" rendered="#{cc.attrs.show}"/>
<p:overlayPanel for="help" showEvent="mouseover" hideEvent="mouseout" hideEffect="fade" >
<p:panel>
#{cc.attrs.helptext}
</p:panel>
</p:overlayPanel>
</composite:implementation>
</html>
and the xhtml that has produced the above screenshot looks like this:
<h:form>
<p:panelGrid columns="3" styleClass="noBorders">
<p:outputLabel for="mydate" value="Date" />
<p:calendar id="mydate" pattern="yyyy/MM/dd" />
<customC:fieldhelp helptext="Help text for date field." show="true" />
<p:outputLabel for="myboolean" value="Send now ?" />
<p:selectBooleanCheckbox id="myboolean" />
<customC:fieldhelp helptext="Help text for boolean field." show="false"/>
<p:outputLabel for="mypwd" value="Your password" />
<p:password id="mypwd" size="30" />
<customC:fieldhelp helptext="Help text for password field." show="true"/>
</p:panelGrid>
</h:form>
Seems to work fine. As you can see I had to reduce the size of the icon otherwise it would be way too big.
Some notes:
The composite doesn't wrap both the help icon and the field. It only
wraps the help icon. This has the downside that you'll need a three
column layout and that the help icon is not displayed right next to
the field. Instead it is displayed in its own column. Not exactly what I wanted.
The help text is conveyed in an attribute. This has the downside that
it cannot contain any HTML markup regardless of the fact that the
destination, the <p:panel>, would happily accept HTML markup.
You can leave out the help icon using the show attribute, however -
because of the three column layout - the <customC:fieldhelp> always
need to exist for each field. This is very clumsy but is again a result
of my lack of knowledge. :-(
I'm sure it can be improved upon if one knew a little more JSF/PrimeFaces than myself.
EDIT
If you want the icon right next to the input field (rather than in a column of its own) then you'll need the <h:panelGroup> tag. You can wrap a group of elements in this tag and <p:panelGrid> (or its sibling : <h:panelGrid>) will then count it as a single element, i.e. occupies one cell only. Something like this:
<h:form>
<p:panelGrid columns="2" styleClass="noBorders">
<p:outputLabel for="mydate" value="Date" />
<h:panelGroup>
<p:calendar id="mydate" pattern="yyyy/MM/dd" />
<customC:fieldhelp helptext="Help text for date field." show="true" />
</h:panelGroup>
<p:outputLabel for="myboolean" value="Send now ?" />
<h:panelGroup>
<p:selectBooleanCheckbox id="myboolean" />
<customC:fieldhelp helptext="Help text for boolean field." show="false"/>
</h:panelGroup>
<p:outputLabel for="mypwd" value="Your password" />
<h:panelGroup>
<p:password id="mypwd" size="30" />
<customC:fieldhelp helptext="Help text for password field." show="true"/>
</h:panelGroup>
</p:panelGrid>
</h:form>
In addition I had to do some CSS tweaking with vertical-align: middle to get the icon vertically aligned with the rest.

Related

JSF updating certain parts of a composite component

I want to develope a JSF composite component using PrimeFaces library.
Basically I want to update my composite component. I have read some SO questions about it (JSF updating a composite component or JSF Updating Composite Component (Primefaces)). But in this case I only want to update certain parts of the component.
Here is an example. My component should be a label/message/value-part of a <p:panelGrid /> to get rid of all the noise of the <p:column/>-tags.
<composite:interface>
<composite:attribute name="label" required="true" />
<composite:attribute name="value" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel value="#{cc.attrs.label}" for="id_inputtext"/>
</p:column>
<p:column>
<!-- message -->
<p:message for="id_inputtext" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="id_inputtext" value="#{cc.attrs.value}"/>
</p:column>
</composite:implementation>
To use this composite component I can simply put it in a panelgrid like so.
<p:panelGrid>
<p:row>
<mycomponent:columnSet id="c1" label="label" value="hello world"/>
<mycomponent:columnSet id="c2" label="label2" value="hello world2"/>
</p:row>
<p:row>
<mycomponent:columnSet id="c3" label="label3" value="hello world3"/>
<mycomponent:columnSet id="c4" label="label4" value="#{bean.someValue}"/>
</p:row>
</p:panelGrid>
In this case I can not surround the content of the component with an HTML container element like <div/> or <span/> like it is described in the above links. That would result in weird HTML because it would be within the generated table.
What I want to do in the example above is to update the <p:outputLabel/>, the <p:message/> and the <p:inputText/> from outside of the component. In a perfect world I want to update these three components independently from each other (but I guess that is even more complicated than updating all at once).
What I currently do to get this to work is kind of cheating. I create a <composite:attribute name="id" /> and give the three components fixed IDs based on a convention using the composite component id. That works but is pretty poor because using the composite component, one needs to know the inner implementation of the it.
Does anyone have an idea to solve this requirement in a nicer way?
<composite:interface>
<composite:attribute name="id" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel id="#{cc.attrs.id}_label"/>
</p:column>
<p:column>
<!-- message -->
<p:message id="#{cc.attrs.id}_message" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="#{cc.attrs.id}_value"/>
</p:column>
</composite:implementation>
EDIT
Thanks for the quick response in the comments.
As to the tag files: Indeed, I must admit that I avoided dealing with tag files because composite components are so much easier to handle, my bad.
Anyway, I just read some stuff, made a quick-and-dirty prototype, but came to the conclusion that (although it might be a good and proper way to use tag files in this label/message/input-situation) I have the same issue as with the composite component: To update the components inside the tag file I need to know the inner implementation of it (that is the same as described in my workaround).
I want to update the composite component/tag file from outside with a «single handle» and treat it as a black box.
If I could wish for a feature I want something to say «do the update» on the composite component/tag file. And within the composite component/tag file I can define which components should be updated if «do the update» is triggered. Something like three separate <div id="#{cc.clientId}"/> surrounding every component I want to update (which obviously is not possible like that).
Because I guess that this is nearly impossible, I would also be happy with a way to update a composite component/tag file as a whole, meaning to update every component within the black box.

Put new component inside existent composition

I'm new in Java Web, and I'm just learning english...
I have multiples composite component, that works fine, like, for example, this code
<composite:interface>
<composite:attribute name="usernameValue" />
</composite:interface>
<composite:implementation>
<h:form>
<h:outputText id="username" value="#{cc.attrs.usernameValue}" />
</h:form>
When I need to use this component, I just do:
<myComposite:myComponent usernameValue="My user name value"/>
this works ok.
But, how to do if I need put more components inside this previously created component, like:
<h:form>
<h:outputText id="username" value="My text 1" />
<p:commandButton value="New button 2"/>
<p:commandButton value="New button 3"/>
<p:commandButton value="New button 4"/>
<h:form/>
Is there any way to do something like:
<myComposite:myComponent usernameValue="This will render default inside composite output text">
<p:commandButton value="New button 1 to render inside my composite"/>
<p:commandButton value="New button 2 to render inside my composite"/>
<p:commandButton value="New button 3 to render inside my composite"/>
<myComposite:myComponent/>
I'm learning, and this time I recreate all composite that I need to use with attribute render="true or false" according the components that I will use, but this is like XGH.
Sorry for my english, I know that i need to improve it...
Thanks in advance...
If I understood your question correctly, what your trying to achieve is what the tag insertChildren does.
In your example, it would be like:
<composite:implementation>
<h:form>
<h:outputText id="username" value="#{cc.attrs.usernameValue}" />
<composite:insertChildren />
</h:form>
</composite:implementation>
and then use the component like you intended:
<myComposite:myComponent usernameValue="This will render default inside composite output text">
<p:commandButton value="New button 1 to render inside my composite"/>
<p:commandButton value="New button 2 to render inside my composite"/>
<p:commandButton value="New button 3 to render inside my composite"/>
<myComposite:myComponent/>
And the commandButtons will be placed where the insertChildren tag was defined.
Here is another example of its usage.

omnifaces highlight component is not working with richfaces 4 bean validation

I have the maven dependency for omnifaces for version 1.11 (as my target is JDK 1.6). Richfaces 4.5.6 final, myfaces 2.2.8. And, against a viewscoped bean I have got this xhtml:
<ui:define name="content">
<f:loadBundle basename="au.com.erb.facility.ui.facility"
var="property" />
<o:highlight styleClass="error" />
<h:panelGrid columns="2">
<rich:validator event="change">
<o:outputLabel value="#{property.absClientNumber}" for="input1" />
<h:inputText id="input1"
value="#{facilityBean.facilityForEdit.alternateKey.absClientNumber}"
label="ABS Client Number" />
<o:outputLabel value="#{property.facilityid}" />
<h:inputText
value="#{facilityBean.facilityForEdit.alternateKey.facilityId}"
label="Facility Id" />
<h:outputLabel value="#{property.rfsAccountGroup}" />
<h:inputText value="#{facilityBean.facilityForEdit.rfsAccountGroup}"
label="RFS Account Group" />
<h:outputLabel value="#{property.rfsAcctCustomerNumber}" />
<h:inputText
value="#{facilityBean.facilityForEdit.rfsAcctCustomerNumber}"
label="RFS Account Customer Number" />
<h:outputLabel value="#{property.rfsAcctLedger}" />
<h:inputText value="#{facilityBean.facilityForEdit.rfsAcctLedger}"
label="RFS Account Ledger" />
</rich:validator>
</h:panelGrid>
</ui:define>
<!-- Buttons that performs actions on a selected record -->
<!-- or navigate to a relevant screen -->
<ui:define name="buttons">
<h:commandButton id="submitButton" value="#{property.submitLabel}"
action="#{facilityBean.save}" styleClass="wideButton"
onclick="#{rich:component('progressWaitModalPanel')}.show()" />
<h:commandButton id="closeButton" value="#{property.closeLabel}"
action="#{facilityBean.close}" styleClass="wideButton"
immediate="true" />
<rich:popupPanel id="progressWaitModalPanel" modal="true">
<f:facet name="header">
<h:outputText value="Processing your request ...." />
</f:facet>
<h:panelGrid columns="1"
style="width: 100%; border-width: 0px; text-align: center;">
<h:outputText value="Please wait..." styleClass="dataValueStyle" />
</h:panelGrid>
</rich:popupPanel>
</ui:define>
The result is nothing. No higlight. No clue what's going on. Have I missed any installation step? I have the css and xmlnamespace in place. Anything else?
I tried to add required="true" as it was shown in the example, but that did not work either. Not sure whether it is due to richfaces bean validation issue.
The <o:highlight> works server side, based on a.o. UIInput#isValid() in JSF component tree. The <rich:validator> works client side and doesn't manipulate JSF component tree.
This indeed doesn't go well together.
I briefly looked into the HTML/JS code of the <rich:validator> showcase and it appears that they don't add a marker style class to the input elements when it's invalid (e.g. PrimeFaces does), so it's going to be hard to write a workaround when continuing the <rich:validator> approach.
You've basically following options:
Maunally write an oncomplete script which finds the validation error messages and then finds the associated inputs and then set the desired marker style class on it.
Report an issue to RichFaces guys and ask them to add a marker style class to invalid inputs via <rich:validator>, so you could style them individually.
Drop <rich:validator> and replace it by server side validation via <f:ajax>.

Image with an InputText of PrimeFaces

I am intending to put an image next to an InputText like a "*" which changes to a green (another image) when something valid is typed in the InputText. How will I be able to put an image along with the InputText?
If a "*" is all you want to add , just add something like
<h:panelGroup styleClass="#{myBean.valid?'geen':'red'}">*</h:panelGroup>
next to your input...
You can also make it interactively using ajax:
<h:form>
<h:inputText value="#{userBean.name}">
<a4j:ajax event="keyup" render="out1,out2" />
</h:inputText>
<!-- For a textual * -->
<h:outputText value="*" styleClass="#{userBean.valid?'green':'red'}" id="out1" />
<!-- For an image -->
<h:graphicImage value="#{userBean.valid?'/img/valid.png':'/img/notvalid.png}" id="out2"/>
</h:form>
Sorry for using RichFaces tag a4j:ajax, I suppose there is an equivalent tag in Primefaces.
Regards,

how to use rich:effect with a4j:include

i've got this jsf code
<f:view>
<rich:page pageTitle="My Page" markupType="xhtml">
...
<rich:panel id="content">
<a4j:include viewId="#{MyBacking.viewId}" />
</rich:panel>
and after trying a number of different ways, I've still not managed to place the following correctly in my code:
<rich:effect for="window" event="onload" type="BlindDown" params="targetId:'<different tags depending on where I place this tag>',duration:2.8" />
My aim is to have the changed element in the a4j:included part of the page change but with the effect in use. I've tried putting it in my included page, or just after the f:view and rich:page tags in the calling page but to no avail. The demo doesn't take includes into account so I'm a bit stuck. Thanks
Just target the a panel inside the rich:panel: targetId:'contentPanel'
and then
<rich:panel ..>
<h:panelGroup layout="block" id="contentPanel">
<a4j:include viewId="#{MyBacking.viewId}">
<ui:param name="targetIdParam" value="putYourTargetIdHere" />
</a4j:include>
<h:panelGroup>
</rich:panel>

Resources