Horizontal placement of components in JSF - jsf

Should be simple but I couldn't find the answer, I would like to place components horizontally instead of vertically.
What I'm trying to achieve is a rich:toolbar with 2 or more rows. I've been trying to do that with a toolbar that has a panelgrid and two panelgroups like this:
<rich:toolbar...>
<f:panelgrid columns="1"...>
<f:panelgroup id="row1" .../> <-- Should be horizontal placement
<f:panelgroup id="row2" .../> <-- Should be horizontal placement
<f:panelgrid/>
<rich:toolbar/>
So how do I make the panelgroup layout horizontal (Or should I use something else?)
Thanks!

You probably already know that JSF in webserver ends up as HTML in webbrowser. In HTML, there are several ways to place elements horizontally (eventually with help of CSS):
Group them in inline elements (like <span> or any element with display: inline;).
Group them in block elements (like <div> or any element with display: block;) and give them all a float: left;.
The JSF <h:panelGrid> renders a HTML <table> element wherein each child component is taken as a <td>. The columns attribute represents the max amount of <td> elements in a single <tr> (so that the <h:panelGrid> knows when to put a </tr><tr> in). The JSF <h:panelGroup> renders a <span> element.
To achieve way 1 with JSF, you just need to group them in separate <h:panelGroup> components.
<rich:toolbar ...>
<h:panelgroup id="row1" ... />
<h:panelgroup id="row2" ... />
</rich:toolbar>
Way 2 can be done the same way, but then with <h:panelGroup layout="block"> instead and a float: left; in their CSS.

Related

Access JSF Custom Tag's id

TL;DR
Is there something like composite's cc.clientId that will give me the id of a custom tag?
Details:
I'd like a custom tag that will render a label, a value, and an icon. When the icon is clicked, a Bootstrap modal is supposed to open up that will edit the value.
<ui:composition>
<div> #{field.label}: #{field.value}
<a class="icon-pencil" data-target="#editForm" data-toggle="modal">
</div>
<h:form id="editForm" class="modal hide fade" role="dialog" ...>
... there's an input here linked to field.value ...
</h:form>
</ui:composition>
I can use the tag with <my:editor />. When I do so within a ui:repeat, an id is prepended to the editForm so that it renders with id j_idt104:editForm. So I need to modify the data-target to include the id.
This would be really easy with a composite component because I have access to the id via cc.clientId:
data-target="\##{cc.clientId}\:editForm"
However, I can't get it to work with a custom tag because I don't know of an EL expression (or something) that will give me access to the id. I could probably wait until after the page is loaded, then use jQuery to inspect the id and set the data-target after the fact, but I was hoping for a more pure-JSF solution.
I'm using JSF 2.1 and Bootstrap 2.3, at the moment.
Answer seems to be no. BalusC says you should replace things like custom tags with "normal" JSF components. In this case, that would mean using the composite component.
If you're deadset on using custom tag, I worked around the issue (with lots of help from the answer here) by using an index in the form's id:
I replaced the ui:repeat with a c:forEach that has access to the item's index:
<table>
<c:forEach items="#{bean.items}" var="item" varStatus="status">
<my:editor index="#{status.index}" ... />
</c:forEach>
</table>
And in the custom tag, I used the index in the data-target:
<tr>
<td>#{label}: #{value}</td>
<td>
<a data-target="\#editForm-#{index}" ... ></a>
<h:form id="editForm-#{index}" ... >
...
</h:form>
</td>
</tr>
The only catch is that c:forEach is a build-time construct (see details in this answer), which is a problem if you need any render-time data (like if you build information up in preRenderView). If you do, then you're better off using ui:repeat with a custom component, and relying on the cc.clientId.

JSF insert space between components in same <div>

Good Evening, i want to know how to insert space between JSF components that lies in same <div> without using <h:outputText value=" " /> i used it and in order to insert the desired space that i want i repeated these tag around 50 times! what are the alternative approaches to do that, these is the <div> :
<div
style="width: 100%; font-size: 20px; line-height: 30px; background-color: gray">
<h:outputText value="–" />
<h:outputLabel value="Notifications ">
<h:graphicImage
value="/resources/images/lunapic_136698680056094_2.gif" />
</h:outputLabel>
/// insert space here
<h:outputLink id="lnk" value="#">
<h:outputText value="Welcome,Islam"></h:outputText>
</h:outputLink>
<p:tooltip for="lnk">
<p:graphicImage value="/resources/images/sofa.png" />
</p:tooltip>
</div>
This is normally to be achieved using CSS, e.g. via the margin property. CSS works on HTML and JSF is in the context of the current question merely a HTML code generator. You should ignore the JSF part in the question and concentrate on the JSF-generated HTML output in order to achieve the requirement. You can see it by rightclick, View Source in a webbrowser. If the HTML needs some altering, then change the JSF source code in such way that it generates exactly the desired HTML.
E.g.
<h:outputLabel value="Notifications" style="margin-bottom: 100px;">
(please note that using style is a poor practice; CSS should preferably be declared in a .css file which you import via <h:outputStylesheet> and reference via styleClass attribute)
Again, this all has nothing to do with JSF. JSF is in the context of this question merely a HTML code generator. If you're brand new to basic HTML/CSS and thus doesn't exactly understand what JSF is producing, then I strongly recommend to take a JSF-pause and learn those basics first.
Unrelated to the concrete problem, the <h:outputLabel> generates a HTML <label> element, but you don't seem to have any HTML input element associated with it. You're in essence abusing the label element for the wrong purpose. Understanding basic HTML and how to write semantic HTML and knowing what HTML output those JSF components exactly generate should push you far in the right direction. In this particular case, you should likely be using <h:outputText> instead.
To insert spaces between components in the same line, you can use img tag with a 1x1 clear image. (Note: this should be the last resort until other options exhausted, see discussion below)
<img width="100" height="10" src="/path-to/dot_clear.gif" />
e.g.
<img width="100" height="10" src="https://raw.githubusercontent.com/jonathanluo/jsf/master/images/dot_clear.gif" />
Enter desired width; for height any number between 1 to 10 will do.
By default, the unit of width and height is pixel
To get a copy of the dot clear image and save it to local resources from https://raw.githubusercontent.com/jonathanluo/jsf/master/images/dot_clear.gif
Right click on the content area and Save as...

How to hide elements in JSF?

Is it possible to hide a div etc based on a condition (like you do in rendered attribute with EL) without having to wrap it in a <h:panelGrid ...> etc with a rendered attribute? It ruins my layout. I just need it for the logic, not the layout.
first of all you should not wrap your elements with h:gridPanel which results in html table
instead you should wrap with h:panelGroup which results in span in html code , you can also add layout="block" to h:panelGroup to make it rendered as div
second you dont not use jstl when hiding div instead do something like this
<div style="display:#{(myBean.hideSomeDiv)?'none':'block'}">My Div Content</div>
or
<h:panelGroup styleClass="#{(myBean.hideSomeDiv)?'hide':''">My Span Content</h:panelGroup>
where in css file add this :
.hide {
display: none;
}
INMO you always better hide in JSF with rendered="#{myBean.renderCondition}"
Take a look at BalusC over here Conditionally displaying JSF components
You could just do this:
<div style="display:#{yourBean.property}"></div>
Where yourBean.property would return 'none' to hide the div

extendedDataTable - height doesn't work

So, like the title says in my case height of the extendedDataTable doesn't work, so my table also doesn't scroll because all rows are shown. I'm using richfaces4.0-final version. So here is my piece of code:
<rich:extendedDataTable
value="#{advancedSearchView.criteria}" var="criteria"
height="50px"
selection="#{advancedSearchView.selection}" id="table"
selectionMode="single">
<rich:column id="criteria_row" filterBy="#{criteria}" filterEvent="onkeyup" width="500px">
<h:outputText value="#{criteria}" />
</rich:column>
</rich:extendedDataTable>
AdvancedSearchView is request scoped bean, and criteria is an array of Strings.
I hope that is enough information. Thank you in advance. A would really appreciate if someone gives me an answer, because I'm struggling with this for a while.
According to the RichFaces 4 VDL (View Declaration Language) documentation, the <rich:extendedDataTable> component does not support the height attribute at all.
Your functional requirement is however understood. You want to render the extended datatable with a height of 50px and make the table body scrollable. You need to achieve this using the usual CSS means by style attribute which can take inline CSS declarations, or by the styleClass attribute which can take CSS classes, like as on almost every other JSF HTML component.
So, with style
<rich:extendedDataTable ... style="height: 50px;">
or, with styleClass (which is also the more recommend practice; separate style from markup)
<rich:extendedDataTable ... styleClass="criteria">
and this piece in a CSS file which you include by <h:outputStylesheet />:
.criteria {
height: 50px;
}

How to make a clickable row in a rich:datatable?

I have a JSF page with a rich:dataTable where, in each row, I put h:commandLinks to lead to pages with the details of the row selected.
I wanted to make the whole row clickable, calling the action method when the user clicks anywhere in the row.
Is that possible without JavaScript?
And if JavaScript is the only way out, what would be the best way do it? Search for a commandLink and "click" it?
Thanks in advance!
I got the whole rows clickable with a bit of styling. I made the links inside the cells occupy the whole cell with display: block; for the links and padding:0 for the cell.
So, here is what you need to do. In the JSF page, set up rowClasses and the links in each cell:
<rich:dataTable value="#{myMB.listaElems}" var="elem" rowClasses="clickable">
<rich:column>
<h:commandLink action="#{myMB.preUpdate(elem)}" value="#{elem.item1}" />
</rich:column>
<rich:column>
<h:commandLink action="#{myMB.preUpdate(elem)}" value="#{elem.item2}" />
</rich:column>
</rich:datatable>
And in the CSS sheet:
tr.clickable td {
padding: 0;
}
tr.clickable td a {
display: block;
padding: 4px;
}
And that's it!
The only downside is that you need to repeat the link in each cell, but the HTTP flow remains simple, you don't need to change any component, and it will work for h:links or good old <a> html links -- a pretty acceptable tradeoff, I'd say. :)
The basic problem is that JSF (core) is tied to the HTML table element for query-result rendering via the dataTable component. Since a JSF dataTable renders as an HTML table, the result is limited to what can be managed in columns (no out-of-the-box row control that I have seen). The HTML/CSS way to do this is quite elegant but in order to accomplish this in JSF, I believe the UIComponent renderer for dataTable would need to be overridden to output this:
<div class="table">
<a href="#" class="row">
<span class="cell">Column-1-Value</span>
<span class="cell">Column-2-Value</span>
</a>
...
</div>
With CSS styles table row and cell representing display:table, display:table-row and display:table-cell; respectively. This makes the row completely clickable but it behaves as a proper table. I have not embarked on re-writing the JSF renderers and solving the JSF commandLink and other component problems to accomplish the rendering as above but that is probably the ultimate answer. I am not a fan of JSF after fighting with it on a few projects now (as compared to lighter weight combinations of concepts from basic HTML/CSS, a sprinkling of JavaScript, clean Java/Servlets, etc).
in your datatable use this one:
<a4j:jsFunction name="selectRow" action="#{userBean.myListener" ...>
<a4j:param name="currentRow" assignTo="#{userBean.selectedRowId}"/>
</a4j:jsFunction>
its called when you select a row, and you can do whatever you want and pass the selected row with the <a4j:param ...as an option you should also be able to call yourLink.click() or something similar, but that wont be the problem to find out...
reference : Richfaces Forum
You may want to try rich:scrollableDataTable. it has attribute onRowClick which you can specify as an event attribute into a4j:support / a4j:ajax nested inside your table. This will make your row clickable.
-cheers :)
For the new RichFaces 4.x, you can use the a4j:commandLink this instead, and make the complete row selectable in CSS. Notice that the 'rowClasses="clickable"' refers to the CSS class to select the whole row:
<rich:column id="fileName" sortable="false" width="618px">
<a4j:commandLink action="#{controller.setSelectedFile(file)}"
oncomplete="window.open('#{menuBar.PrintPage}?outputType=pdf', '_blank');"
rendered="#{not controller.getButtonDisabled(file)}"
execute="#this" limitRender="true">
<h:outputText value="${file}"
style="text-align:left;width:100%;min-width:400px;"
title="${file.name} is viewable.">
<f:converter converterId="MVC.View.Converter_FilePath" />
</h:outputText>
</a4j:commandLink>
</rich:column>
Use this CSS class to select the whole row:
tr.clickable td {
padding: 0;
}
tr.clickable td a {
display: block;
padding: 4px;
}

Resources