Misaligned columns in Primefaces datatable - primefaces

I'm trying to make a datatable showing column as easy as possible - like auto width.
It misaligns the columns compared to the header, like these:
My code looks like this:
<p:dataTable id="datalist2" value="#{item.formItemCollection}"
var="item2" scrollable="true" scrollHeight="100" tableStyle="width:auto"
emptyMessage="#{bundle.EmptyMessage}" >
<ui:include src="/view/formItem/formItemListRow.xhtml">
<ui:param name="rowItem" value="#{item2}"/>
<ui:param name="controller" value="#{formItemController}"/>
</ui:include>

Related

How to hide some column in columns tag in primefaces?

I have a table which I want to hide particular column as below.
For example, I want to hide 3 last columns under the tag <p:columns> </p:columns>
<p:dataTable id="dynaDataTable" var="row" value="#{onListBean.rowList}" style="font-size:12px;"
selectionMode="single" selection="#{onListBean.selectedRow}" rowKey="#{row.s_nr}"
widgetVar="dynaTable" emptyMessage="Empty!" rowIndexVar="rowIndex"
scrollable="true" scrollHeight="100%">
<p:column id="rowNumber" exportable="false" headerText="#" style="max-width:50px; width:20px" >
<h:outputText value="#{rowIndex+1}" />
</p:column>
<p:columns headerText="#{column.header}" value="#{onListBean.columns}" var="column" >
<div style="text-align: center;">
<h:outputText value="#{row[column.property]}"/>
</div>
</p:columns> </p:dataTable>
Any Idea?
Just create a method in your bean which will return the columns you want to display, and use that with <p:columns value="...". If that is somehow not possible, you can also use the visible attribute, for example visible="#{column.header ne 'excludeMe'}".
If you are looking to display columns based on the available screen width, you should have a look at either the responsivePriority property, or <p:dataTable reflow="true".
See also:
https://www.primefaces.org/showcase/ui/data/datatable/responsive.xhtml
I couldn't understand from your question if you need it done using a UI component or not. If yes, Primefaces has a pretty nice component <p:columnToggler /> which lets you hide and show the table columns whenever you want.
If you were talking about the other scenario, I still think you could do some trick with columntoggler while not displaying it in the UI.

Include page with specific anchor

I'am a beginner in jsf and I want to open an html page in a p:dialog.
When I use the <ui: include> to display the page like this:
<p:dialog header="Dialog"
widgetVar="dlg"
resizable="false"
dynamic="true"
fitViewport="true">
<ui:include src="/resources/md.html" />
</p:dialog>
it works with no problem, but when I want to open the page in a specific anchor like this:
<p:dialog header="Dialog"
widgetVar="dlg"
resizable="false"
dynamic="true"
fitViewport="true">
<ui:include src="/resources/md.html#anchor" />
</p:dialog>
it doesn't work.
Can somebody help please.
Your attempt fails because your md.html is statically included inside 'parent' jsf page. Therefore only parent jsf page can be used to achieve 'go to anchor' functionality.
To achieve what you want with an included page inside p:dialog, I would use simple java script.
JS
Add this JS function to your parent jsf page (page where dialog is defined)
function gotoAnchor(anchorID) {
document.getElementById(anchorID).scrollIntoView();
}
XHTML
Add onShow attribute on p:dialog like this
<p:dialog ... onShow="gotoAnchor('anchorID')" ...>
<ui:include src="/resources/md.html" />
</p:dialog>
where anchorID is id of your anchor element inside md.html (in your example, its value is 'anchor').
On this way, when your p:dialog is shown, function gotoAnchor will be executed forcing page to scroll on required element.
This is another solution using iframe tag, it works perfectly:
<p:commandLink value="iframe" onclick="PF('dlg').show()" />
<p:dialog header="Dialog" widgetVar="dlg">
<iframe height="500" width="800" src="/md.xhtml#anchor"></iframe>
</p:dialog>
No js need.

How to hide/show a row in a panelgrid based on data entered in another row

I have a panelGrid with a row containing a selectCheckBoxMenu and another row which should be shown or hidden based on the selection.
Updating the entire panel when the selection is changed is not desired, because the selectCheckBoxMenu would be refreshed and the user would have to open the dropdown again for each item he wants to select.
Updating the controls to be hidden or shown can't solve the problem either because they can't be updated if they are not shown because rendered was false before.
So, I wrapped these controls in a Fragment and update those fragments. Functionally that's OK, but now I have an ugly layout because in most situations the controls will be hidden and a small empty row is shown.
Is it possible to get rid of that ugly empty row without breaking the functionality again?
My xhtml looks like this:
<p:panelGrid id="panel" columns="2" border="0" cellpadding="5"
cellspacing="2">
...
<h:outputLabel value="Type" />
<p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"
filter="true" filterMatchMode="contains"
panelStyle="width:300px" valueChangeListener="#{controller.onChange}"
updateLabel="true">
<p:ajax update="sclabel scfield" />
<f:selectItems value="#{deviceTypeBean.alldts}" var="dt"
itemLabel="#{dt.name}" itemValue="#{dt}"/>
</p:selectCheckboxMenu>
...
<p:fragment id="sclabel">
<h:outputText value="Detail" rendered="#{controller.detailRequired}"/>
</p:fragment>
<p:fragment id="scfield">
<p:selectCheckboxMenu rendered="#{controller.detailRequired}" converter="#{detailConverter}"
value="#{controller.criteria.detail}" label="All details"
filter="true" filterMatchMode="contains"
style="width:300px;" scrollHeight="100"
updateLabel="true">
<f:selectItems value="#{detailConverter.values}" var="adetail"
itemLabel="#{adetail.name}" itemValue="#{adetail}" />
</p:selectCheckboxMenu>
</p:fragment>
...
</p:panelGrid>
Cause
The empty row contains padding. The table row and table cell html elements are created by the panelgrid because it renders those for every row and as soon as there some child element a row is rendered. And they have styleclasses on them which are set by the panelgrid and refer to styles which contain padding. The fragments, even if they don't render anything themselves are enough to trigger that.
Remark: We are using the Modena theme from Primefaces. So, the padding is part of the Modena theme.
Extract of the Modena stylesheet which causes the problem:
.ui-panelgrid .ui-panelgrid-cell {
border-width: 1px;
border-style: solid;
border-color: inherit;
padding: 4px 10px;
}
Solution
I did the following changes:
I explicitly specified rows and columns using primefaces row and column components and added a style class "ui-panelgrid-cell-nopadding" to the columns of the row which I need to hide. I added the style below to my stylesheet so that, that style class removes/overrides padding from that cell which was added by the panelgrid.
.ui-panelgrid .ui-panelgrid-cell-nopadding {
padding: 0px 0px;
}
I added a div around the controls in the cells and applied the class ui-panelgrid-cell to it to add the padding which I removed from the cells.
Remark: I tried a panel first for this, but then it became more complicated because the Primefaces panel also adds styleclasses which caused inconsistent layout with the other rows in my panelgrid (fontsize was changed).
I added a second fragment between the fragments I already had and the div's and I moved the rendered attribute from the controls inside the cells to these fragments. So that the padding defined on the div is no longer there if I don't want the row to be rendered.
One fragment is not enough anymore, because I needed one with an id to be able to update it via ajax and a second with the rendered attribute. If you put those attributes on the same fragment, you can't make it visible anymore as soon as it's hidden. Moving the id's to the explicitly defined columns is also not possible because then these cells behave strangely probably because they are empty when rendering the panelgrid initially. When the cells were updated to make them visible, the content of both the cells of my row appeared in the left cell and the right cell remained empty.
After that, I had a border around the div's because that is specified in the Modena style which I applied to the div's to have the padding that I removed from the cells. And because the content of the div's was smaller than the cell, I had an extra border, I didn't want. So I added something to my stylesheet to remove that border.
.ui-panelgrid .ui-panelgrid-cell-nopadding .ui-panelgrid-cell {
border:none; border:0px;
}
My xhtml now looks like this:
<p:panelGrid id="panel" border="0">
...
<p:row>
<p:column>
<h:outputLabel value="Type" />
<p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"
</p:column>
<p:column>
filter="true" filterMatchMode="contains"
panelStyle="width:300px" valueChangeListener="#{controller.onChange}"
updateLabel="true">
<p:ajax update="sclabel scfield" />
<f:selectItems value="#{deviceTypeBean.alldts}" var="dt"
itemLabel="#{dt.name}" itemValue="#{dt}"/>
</p:selectCheckboxMenu>
</p:column>
</p:row>
...
<p:row>
<p:column styleClass="ui-panelgrid-cell-nopadding">
<p:fragment id="sclabel">
<p:fragment rendered="#{controller.detailRequired}">
<div class="ui-panelgrid-cell">
<h:outputText value="Detail"/>
</div>
</p:fragment>
</p:fragment>
</p:column>
<p:column styleClass="ui-panelgrid-cell-nopadding">
<p:fragment id="scfield">
<p:fragment rendered="#{controller.detailRequired}">
<div class="ui-panelgrid-cell">
<p:selectCheckboxMenu converter="#{detailConverter}"
value="#{controller.criteria.detail}" label="All details"
filter="true" filterMatchMode="contains"
style="width:300px;" scrollHeight="100"
updateLabel="true">
<f:selectItems value="#{detailConverter.values}" var="adetail"
itemLabel="#{adetail.name}" itemValue="#{adetail}" />
</p:selectCheckboxMenu>
</div>
</p:fragment>
</p:fragment>
</p:column>
<.p:row>
...
</p:panelGrid>
For example put an Id to row:
in javascript :
if (condition that you need)
{
document.getElementById("form:idEmpresa").style.display = "none";
}
Ready

primefaces 5.1.6 <p:printer> print datable formatting issues

Our project recently upgraded from primefaces v4.0.24 to primefaces v5.1.6.
Upon testing there it was found that when the datatable is printed to printer or PDF there were formatting issues. The column headers were not correctly justified especially the one having longer values.
However it fits correctly if I change the layout to landscape.
I want the data to be correctly justified in portrait mode.
This wasn't the problem with previous version of primefaces.
The page consists of commandlink and datatable.
When the user clicks on commandlink the id of the datatable is passed to p:printer.
Here is the code
<h:commandLink styleClass="ui-icon-export-print" title="#{webmsg['action.export.print.hint']}">
<p:printer target="companyTable" />
</h:commandLink>
<p:dataTable id="companyTable" widgetVar="companyTable" var="company" value="#{companies}"
sortBy="#{company.shortName}" sortOrder="ascending" filterEvent="enter"
filteredValue="#{companyForm.filteredCompanies}">
<f:facet name="header">
<h:outputText value="#{appmsg['label.companies']}" />
</f:facet>
<p:column sortBy="#{company.shortName}" filterBy="#{company.shortName}" filterMatchMode="contains" >
<f:facet name="header">
<h:outputText value="..." />
</f:facet>
<h:outputText value="#{company.shortName}" />
</p:column>
.....
</p:dataTable>
The data is either cuttoff or it touches the column border.
If I go to print options and change the default size of paper from A4 to Tabloid, then the data correctly fits within the column.
There should be some way to autofit the data with the default paper size.
Any ideas or clues to fix the formatting issue would be appreciated. Thanks.
Yes, you can use css for this. It has media types so you can tune things for just print devices and leave the screen things untouched. You can also change the ['paper size']there

Primefaces datatable columnGroup header stomps on header facet with sortBy and filterBy

My goal is to produce a table with two header rows. The first with a few column-spanning cells, the second with all 1-cell headers, but with sortBy and filterBy enabled.
<p:dataTable .... >
<p:columnGroup type="header">
<p:row>
<p:column colspan="3" headerText="my header 1" />
<p:column colspan="3" headerText="my header 2" />
</p:row>
</p:columnGroup>
<p:column sortBy="#{myBean.var1}" filterBy="#{myBean.var1}" headerText="var1">
<h:outputText value="#{...var1}" />
</p:column>
.
.
</p:dataTable>
I can get either the columnGroup to show up or the per-column headerText with sortBy and filterBy, but not both. When I mix them, the header components from the per-column header row disappears.
As it turns out, it is possible to nest dataTables via the subTable component. This showcase example demonstrates nesting a subTable in a larger dataTable, there-by achieving filtering and sorting combined with columnGroups in the headers.