Apply styleClass to parent panelGrid element and not to children - css

I'm trying to apply a styleClass to a h:panelGrid without applying it to its children:
<h:panelGrid id="mainPanelGrid" columns="2" width="100%" styleClass="topAligned" >
<p:fieldset id="fs1" legend="fs1" style="width: max-content">
<h:panelGrid columns="3">
<p:outputLabel for="id1" value="#{messages.label_application}" />
<p:selectOneMenu id="id1" required="true" value="som">
<f:selectItem itemLabel="#{messages.label_select}" noSelectionOption="true" />
<f:selectItems value="#{bean.availableItems}" />
</p:selectOneMenu>
<p:message for="id1" />
</h:panelGrid>
</p:fieldset>
<p:fieldset id="fs2" legend="fs2" style="width: max-content">
<h:panelGrid columns="3">
<!--more fields-->
</h:panelGrid>
</p:fieldset>
</h:panelGrid>
My topAligned css:
.topAligned td{
vertical-align: top !important;
}
The problem is that I need to top align the two fieldset and that works well with the styleClass I apply, but it also applies this styleClass to all the children. Therefore, all the fields (outputLabel, selectOneMenu, etc...) of the two fieldset get top aligned too...
I tried all the different ways to specify the top alignment from this question but without success... I also tried to look at the html source but it gets a bit confusing with all the jsf and primefaces stuff...
If you know a trick that will work...

With
.topAligned td{
vertical-align: top !important;
}
and the JSF-generated HTML output
<table class="topAligned">
...
</table>
you're basically applying the style on every single <td> element of the <table>, also those of the nested <table>s.
If you want to apply the style on only the immediate <td> elements of the parent <table>, then you should be using columnClasses attribute instead:
<h:panelGrid ... columnClasses="topAligned,topAligned">
with
.topAligned {
vertical-align: top;
}
This will end up in the generated HTML output as follows:
<table>
<tbody>
<tr>
<td class="topAligned">...</td>
<td class="topAligned">...</td>
</tr>
</tbody>
</table>
and not be applied on the <td>s of the nested <table>s.
Note that I also removed the nonsensicial !important workaround. It's supposed to be used only when you want to override a hardcoded style by an external CSS style.
Also note that this problem is not specifically related to JSF. JSF is in the context of this question merely a HTML code generator. You'd have had exactly the same problem when dealing with "plain vanilla" HTML/CSS. The problem is more in the lack of familiarity with basic HTML and CSS. On http://htmldog.com you can find decent HTML/CSS tutorials.

Related

How can I set ui-panelgrid-cell padding for a specific p:panelGrid?

This is my page structure:
<p:panelGrid>
<p:row>
<p:column>
<p:panelGrid id="innerPg_1">
</p:column>
<p:column>
<p:panelGrid id="innerPg_2">
</p:column>
</p:row>
</p:panelGrid>
I would like to override the padding attribute on the ui-panelgrid-cell class, only for the panelGrid with id="innerPg_1", by making my own css rule.
How can I do that?
Tried with the following rule:
#innerPg_1 .ui-panelgrid-cell {
padding: 1px 1px !important;
}
but it doesn't work. Shouldn't it be a wrong rule?
The produced html part is:
<td role="gridcell" class="ui-panelgrid-cell">
<tabled id="formId:innerPg_1"class="ui-panelgrid ui-widget role="grid">
Well, the id of the component in the produced html isn't innerPg_1, it is formId:innerPg_1.
So, in your css you should use the following rule: #formId\:innerPg_1 .ui-panelgrid-cell {...}. (Don't forget the slash!!)
I'm not sure what are you trying to achieve, but at first, try just to change the background-color, just to check if the rule is being overrided
Also, using styleClass instead of id might be a better option, so you could reuse it for another panelGrid

Applying CSS classes only to the parent (current) p:panelGrid

The following <p:panelGrid> contains another <p:panelGrid>s.
<p:panelGrid columns="2" styleClass="panelgrid-noborder">
<p:panelGrid columns="1">
<h:outputText value="1"/>
<h:outputText value="2"/>
</p:panelGrid>
<p:panelGrid columns="1">
<h:outputText value="1"/>
<h:outputText value="2"/>
</p:panelGrid>
</p:panelGrid>
Just as an example, I need to remove all borders only from the parent/outer(most) <p:panelGrid>.
The following CSS class,
.panelgrid-noborder.ui-panelgrid tr, .panelgrid-noborder.ui-panelgrid .ui-panelgrid-cell {
border: none;
}
Removes borders from all <p:panelGrid>s.
I also tried using a plain CSS class like,
.panelgrid-noborder {
border: none;
}
and give it to the columnClasses attribute - columnClasses="panelgrid-noborder" but it does not remove borders at all.
How to remove borders from a parent <p:panelGrid> i.e CSS classes should only be applied to the current <p:panelGrid> to which theses classes are specified? This should not affect any other <p:panelGrid>s.
The selector .panelgrid-noborder.ui-panelgrid tr basically means "match every <tr> of an element having class panelgrid-noborder ui-panelgrid".
You only want to match the immediate child. You need to use a more specific selector for that, specifically the child combinator selector E > F.
So, this should do:
.panelgrid-noborder.ui-panelgrid > tbody > tr,
.panelgrid-noborder.ui-panelgrid > tbody > tr > td {
border: none;
}
Please note that browsers implicitly put <tr> elements in <tbody> when no <thead> or <tfoot> is specified. You can see it in browser's HTML DOM tree inspector.
See also:
CSS tutorial

Force linebreak OutputLabel

I have an outputLabel which contains a lot of text (about 5000 characters of text), the outputLabel has to add a new line after the line is about 200px, is this possible?
<p:outputLabel value="#{object.body}" />
<p:outputLabel value="#{object.body}" style="width: 200px" />
This code doesn't work:
public String getBodyWithLineBreaks(){
return body.replaceAll("(.{100})", "$1<br/>");
}
It is also not a solution because this method does not look if a word is finished, it just starts a new line at the 100th character.
Some more code:
<p:dataTable id="dataTable" var="object" value="#{notificationOverview.objects}">
<!--Some more columns...-->
<p:rowExpansion>
<h:panelGrid id="display" columns="2" cellpadding="4" style="width:300px;"
styleClass=" ui-widget-content grid">
<f:facet name="header">Notification Information</f:facet>
<h:outputText value="Sender:"/>
<h:outputText value="#{object.sender.username}"/>
<h:outputText value="Time send:"/>
<h:outputText value="#{object.dateSend}">
<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss"/>
</h:outputText>
<h:outputText value="Title:"/>
<h:outputText value="#{object.title}"/>
</h:panelGrid>
<br/><br/>
<div style='width: 200px;'>
<h:outputText value="#{object.body}" />
</div>
</p:rowExpansion>
</p:dataTable>
The <p:outputLabel> generates a HTML <label> element which is by default an inline element. You can't set the dimensions of an inline element. You can only set it on a block element.
One way would be adding display: block to the style.
<p:outputLabel value="#{object.body}" style="display: block; width: 200px;" />
Additionally, given that this is inside a <p:dataTable> cell, which has by default its CSS white-space property set to nowrap, you need to set it back to normal. This can be set on the same component, but this is preferably to be set on the parent <p:column> itself:
<p:column style="white-space: normal;">
Note: as part of a good practice, you should prefer styleClass over style.
Unrelated to the concrete problem, the HTML <label> element is designed to label an input element which is identified by for attribute. I.e. when you click on it, the associated input element retrieves focus (and a checkbox/radiobutton get selected). When validation is performed, the label is used to identify the input element. However, the fact that you're trying to display 5000 characters inside a label element, which is completely user unfriendly when used as a real label, suggests that you're actually abusing the label for the wrong purpose of displaying "plain text". You should be using <h:outputText> instead. This generates a HTML <span> element which is by default also an inline element. So the above answer applies on that as well:
<h:outputText value="#{object.body}" style="display: block; width: 200px;" />

JSF panelgrid alignment to top

I see there are some answers posted for this. tried almost all of them with several permutation-combination.. but nothing seems to be working.
components inside panelgris are always middle aligned, instead of top.
tried whatever they said in the below post.
How to control alignment of DataTable inside of a PanelGrid?
Please let me know if there is a remedy.
The <h:panelGrid> renders a HTML <table> element. The vertical alignment of a table cell <td> defaults indeed to middle. You want to make it to be top instead. This is easy with CSS.
<h:panelGrid styleClass="foo">
with
.foo td {
vertical-align: top;
}
If you have a table inside the panelgrid for which you'd like to keep the default table cell vertical alignment of middle, then you need to alter the CSS as follows:
.foo>tbody>tr>td {
vertical-align: top;
}
so that only the panelgrid's own table cells are top aligned.
To learn all about CSS, check http://www.csstutorial.net.
Use the panelGrid's columnClasses attribute to identify a CSS class that includes the vertical-align: top; style:
<h:panelGrid columns="2" columnClasses="topAligned">
...
</h:panelGrid>
and the CSS file:
.topAligned {
vertical-align: top;
}
The contents of the first column in the panelGrid will then be top-aligned within their cells.
Use the styleClass for the panelGrid as in the following example code:
<h:panelGrid columns="2" styleClass="top-aligned-columns" cellpadding="5" style="display:block" cellspacing="5">
<p:outputLabel value="#{resources['IDNumber']}" />
<p:inputText id="txtIDNumber" value="#{applicantBean.personal.idNumber}" />
</h:panelGrid>
Then in the css configure as follows:
.top-aligned-columns td{
vertical-align: top;
}
With this method you will be able to not only top-align the rows but you can also apply the same styleClass to other panelGrids within the encompassing panelGrid.
For example:
<h:panelGrid columns="3" styleClass="top-aligned-columns" cellpadding="5" style="display:block" cellspacing="5">
<p:panel id="pnlApplicant" header="#{resources['ApplicantHeader']}" styleClass="no-border">
<h:panelGrid columns="2" cellpadding="5" style="display:block" cellspacing="5" styleClass="top-aligned-columns">
<p:outputLabel value="#{resources['IDNumber']}" />
<p:inputText id="txtIDNumber" value="#{applicantBean.personal.idNumber}" >
<p:ajax event="change" process="#this" update="tvQuickScore"/>
</p:inputText>
<p:outputLabel value="#{resources['Name']}" />
<p:inputText id="txtFirstname" value="#{applicantBean.personal.firstName}" />
<p:outputLabel value="#{resources['Surname']}" />
<p:inputText id="txtSurname" value="#{applicantBean.personal.lastName}" />
</h:panelGrid>
</p:panel>
</h:panelGrid>
</p:panel>

How to align items in a <h:panelGrid> to the right

How would I align everything in my below to the far right?
<div id="container">
<h:form id="authenticate">
<h:panelGrid columns="5" cellpadding="6">
<h:inputText id="email" value="" />
<p:watermark for="email" value="Email"/>
<h:inputSecret id="password" value="" />
<p:watermark for="password" value="Password"/>
<p:commandButton id="login" value="Login" align="right"/>
</h:panelGrid>
</h:form>
</div>
The <h:panelGrid> renders a HTML table. You basically want to apply text-align: right; on every <td> element it renders. With the current code, easiest would be to apply the following:
#authenticate table td {
text-align: right;
}
You can of course also be more specific, e.g. giving the <h:panelGrid> its own styleClass and defining a rule in CSS (which would be applied directly on the rendered HTML <table> element).
<h:panelGrid styleClass="className">
with
.className td {
text-align: right;
}
You can also give each <td> element its own class by columnClasses attribute which accepts a commaseparated string of CSS classnames which are to be applied repeatedly on the <td> elements. If you want to apply the same class on every <td> element, just specify it once:
<h:panelGrid columnClasses="className">
with
.className {
text-align: right;
}
As an extra hint: rightclick the webpage in webbrowser and choose View Source, then you'll understand better what JSF is all exactly generating.
actually in same form i used <p:panel> and got good result. looks like ;
<p:panel styleClass="ui-panel-titlebar ui-widget-header ui-helper-clearfix ui-corner-all">
<p:commandButton value="Add New Tab"
actionListener="#{xxx.createNewTab}" process="#this"
update="tabView" style="float:right !important;margin:0px 0px 3px 0px;" />
</p:panel>
A little late, but might help someone, as it was what I needed...
If the alignment is not limited to this specific table, but rather the default format for all table cells, then just add this to your CSS file:
td {
text-align: right;
}
Then, all <td> elements, including those generated by JSF, will be formatted that way.

Resources