change color of inputtextfield on select booleancheckbox - jsf-2

I have a form in which there is a selectbox, and a inputtext field with default red color.
I want to change color of inputtextfield when that checkbox is selected.
How can I do that?
I am trying to achieve in this way, but unable to get change color.
pojo:
private Boolean changeColor=false;
private boolean sign1;
public void ChangeColorEvent(){
System.out.println("inside color change event");
changeColor=true;
sign1=true;
}
<h:outputText value="understood and Signed?: " />
<p:selectBooleanCheckbox label="Yes" value="#{patient.sign1}" >
<p:ajax update="hppa1" listener="#{patient.ChangeColorEvent}" />
</p:selectBooleanCheckbox>
<h:panelGroup>
<p:inputText id="hppa" size="5" style="color:White;background:Red;" rendered="#{!patient.changeColor}" />
<p:inputText id="hppa1" size="5" rendered="#{patient.changeColor}" style="color:White;background:Green;"/>
</h:panelGroup>

You can use the approach suggested by Daniel. Or a slightly different version would be this
<p:inputText id="hppa1" size="5" style="#{patient.changeColor eq true ? 'color:White;background:Green;' : 'color:White;background:Red;'}"/>
Saves you unnecessary markup and processing!
UPDATE: btw, you can very well handle these events in Javascript if you do not need any server side reflection of the sign1 boolean flag

Alternative approach with jQuery using styleClass as #Daniel mentioned would be like this :
Define style classes in your css:
.red {
background-color: red;
}
.blue{
background-color: blue;
}
Have just one p:inputText (your approach with switching between two of them is really wrong) and add a styleClass="red" to it.
<p:inputText id="inputID" styleClass="red"/>
Then define this function :
<script type="text/javascript">
function changeColor(param){
if (jQuery("[id*="+param+"]").hasClass('red')){
jQuery("[id*="+param+"]").removeClass('red');
jQuery("[id*="+param+"]").addClass('blue');
}
else {
jQuery("[id*="+param+"]").removeClass('blue');
jQuery("[id*="+param+"]").addClass('red');
}
};
</script>
And use it in p:selectBooleanCheckbox:
<p:selectBooleanCheckbox onchange="changeColor('inputID')"/>
Note 1: [id*="+param+"] in jQuery is because primefaces adds ids to your element (p:inputText) depending on what wraps it (eg. form, dataTable, ...). With [id*="+param+"] you can basically escape these added ids and find your desired inputText.
Note 2: If you want to work only with red class you can use :
function changeColor(param){
jQuery("[id*="+param+"]".toggleClass('red'));
};
EDIT: This approach has no problem with initial stage which you mentioned in comment to #NikhilPatil answer.

for start add id to your <h:panelGroup id="myWrapper">
and change the p:ajax to this <p:ajax update="myWrapper" ....
You can't update elements that are not rendered... read this Similar issue
Or , an alternative solution (since you are using primefaces) is to change your <h:panelGroup> into <p:outputPanel id="panel" autoUpdate="true"> and leave alll the rest the way it was
Output panel is a container element with several use cases, this example uses an autoUpdate outputPanel to update a component page which doesn't exist on page initially and rendered based on a condition.
Output Panel
But the way you are trying to change color is completely wrong... instead of hiding and displaying the element you should modify the css attributes of ONE element...
define 2 css classes like this
.classOne{
color:White;
background:Red;
}
.classTwo{
color:White;
background:Green;
}
.classThree{
color:White;
background:Blue;
}
and change the styleClass="" of your <p:inputText id="hppa1"
like this
<p:inputText id="hppa1" styleClass="#{patient.className}".....
add String changeColor to your bean + getter/setter and change its values from classOne to classTwo ....

Related

Rendering of an element depending on primefaces rating

I started using primafaces and I came up with the following scenario. The user rates and element and if the rating is valid then a span block appears or it hides depending the case. I am based on the example here: (http://www.primefaces.org/showcase/ui/input/rating.xhtml ) with the ajax approach. Note that a rate is valid if the user clicks on any star. So here's what I've done so far:
<h:form>
<p:panelGrid>
<p:row>
<p:column>
<p:rating value="#{searchBean.dateWeight}">
<p:ajax event="rate" listener="#{searchBean.addDatetoWeights}"
update="dates" render="dates" />
<p:ajax event="cancel"
listener="#{searchBean.removeDatefromWeights}"
update="dates" />
</p:rating>
<h:panelGroup id="dates" rendered="#{searchBean.dateRated}">
<h:outputText value="test"></h:outputText>
</h:panelGroup>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
segment of the bean:
boolean dateRated;
int dateWeight;
public void addDatetoWeights(){
dateRated=true;
weights.put("date",dateWeight);
System.out.println(dateRated);
}
public void removeDatefromWeights(){
dateRated=false;
if(weights.containsKey("date"))
weights.remove("date");
}
Let's go back to the basics: HTML and JavaScript. It's important to also know them before diving into JSF. JSF is in the context of this question merely a HTML/JS code generator.
With <p:ajax update="dates"> you're basically telling JavaScript to grab the HTML element by the given ID and then replace its contents with the new contents retrieved from server in ajax response. However, as the <h:panelGroup id="dates"> is in first place never rendered to the HTML output, JavaScript can't find the element by document.getElementById() stuff in order to replace its contents and then just ignores the instruction.
Instead, the <p:ajax update="dates"> must refer a component which is always rendered, so that JavaScript can actually find it. Only its contents can be conditionally rendered.
Here's a rewrite:
<h:panelGroup id="dates">
<h:outputText value="test" rendered="#{searchBean.dateRated}" />
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

Primefaces inputtext focus at the end of the text

Here a snippet of my JSF:
<p:tabView id="tabView" var="tab" value="#{data.tabs}" widgetVar="tabViewWidget"
activeIndex="#{data.newActiveTabIndex}">
<p:ajax event="tabClose" listener="#{logic.closeTab}" />
<p:tab title="#{tab.content.title != null ? tab.content.title : '&lt;new&gt;'}"
closable="#{tab.isClosable and data.tabs.size() > 2}">
<h:outputText value="#{tab.id} Test" />
<p:focus rendered="#{data.componentIdToFocus != null}" for="#{data.componentIdToFocus}" />
<p:inputText id="test" value="#{tab.content.title}">
<p:ajax event="keyup" listener="#{logic.setFocusingComponent}" update=":form:tabView" />
</p:inputText>
</p:tab>
</p:tabView>
The intent is that there is a textfield within each tab that updates the title of the tab while writing.
The given snippet works except that p:focus places the cursor at the beginning of the text that is already written. I want the cursor to be placed at the end of the text already written. So that a user can type and while he/she is typing the title adapts automatically.
I hope my case is clear.
Does anybody have a solution for that?
Best regards,
Florian
You can use the onfocus="this.value=this.value" trick to "deselect" the value so that the cursor automagically ends up in the end of the value. This should work as good for the <p:inputText> as it basically generates just a <input type="text"> element.
<p:inputText ... onfocus="this.value=this.value" />
See also:
Use JavaScript to place cursor at end of text in text input element
Unrelated to the concrete problem, I wouldn't use ajax and such on keyup event and an update of the whole tabview. This seems to be quite expensive. I'd rather do a simple HTML DOM traversion and manipulation here by JS/jQuery.
E.g.
<p:inputText ... onkeyup="updateTitle(this)" />
with
function updateTitle(inputInTab) {
var panelId = $(inputInTab).closest(".ui-tabs-panel").attr("id");
$("a[href='#" + panelId + "']").text(inputInTab.value);
}

Trigger/activate the RowEditor from bean for a primefaces In-Cell editing enabled p:dataTable

I have a primefaces p:dataTable with InCell editing enabled and want to trigger/activate the RowEditor for the newly added row.
Excerpt of XHTML
<p:commandButton id="btnAddEntry" value="Add new row" actionListener="#{myBean.addNewCar}" ... update="carTable growl" process="#this carTable ..."/>
<p:dataTable id="carTable" var="car" value="#{myBean.cars}" ... editable="true">
<p:column ...>
<p:cellEditor>
...
</p:cellEditor>
</p:column>
...
<p:column ...>
<p:rowEditor />
</p:column>
...
</p:dataTable>
Here is what i have so far for the bean method:
public void addNewCar() {
Car newCar = new Car();
cars.add(newCar);
FacesContext facesContext = FacesContext.getCurrentInstance();
UIComponent uiTable = ComponentUtils.findComponent(facesContext.getViewRoot(), "carTable");
DataTable table = (DataTable) uiTable;
final AjaxBehavior behavior = new AjaxBehavior();
RowEditEvent rowEditEvent = new RowEditEvent(uiTable, behavior, table.getRowData());
rowEditEvent.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
table.broadcast(rowEditEvent);
}
i don't know
if this is the correct approach
in case yes, which object to pass to the constructor RowEditEvent(UIComponent component, Behavior behavior, Object object) as the 3rd parameter
If you have only one data table in the facelet try to use this
oncomplete="jQuery('.ui-datatable-data tr').last().find('span.ui-icon-pencil').each(function(){jQuery(this).click()});
Add this to the command button. This should work.
I used the execute(..) method of class RequestContext in my create method. This allowed me to first calculate the index of the row to go into edit mode and to include it dynamically in the javascript:
RequestContext.getCurrentInstance().execute("jQuery('span.ui-icon-pencil').eq(" + rowToEditIndex + ").each(function(){jQuery(this).click()});");
Hope this helps.
You can add an unique styleClass to the dataTable, and one javascript function in the commandButton:
So add to the table:
styleClass="myTable"
And to the button:
oncomplete="$('.myTable tbody.ui-datatable-data tr:last-child td span.ui-row-editor span.ui-icon-pencil').click()"
And your code will look like this:
<p:commandButton id="btnAddEntry" value="Add new row" actionListener="#{myBean.addNewCar}" ... update="carTable growl" process="#this carTable ..." oncomplete="$('.myTable tbody.ui-datatable-data tr:last-child td span.ui-row-editor span.ui-icon-pencil').click()"/>
<p:dataTable styleClass="myTable" id="carTable" var="car" value="#{myBean.cars}" ... editable="true">
<p:column ...>
<p:cellEditor>
...
</p:cellEditor>
</p:column>
...
<p:column ...>
<p:rowEditor />
</p:column>
...
</p:dataTable>
This solution aims to resolve a few drawbacks of the original answer of:
oncomplete="jQuery('.ui-datatable-data tr').last().find('span.ui-icon-pencil').each(function(){jQuery(this).click()});"
The above statement retrieves all "tr" elements which are descendants (at any level) of elements with the ".ui-datatable-data" class. The potential issues with that are:
As mentioned by #Gnappuraz, if there are multiple p:datatable's in the document, this statement will choose the last table.
Additionally, I ran into a problem where even with one datatable, a column with a p:selectOneRadio component will also render a html table (that contains "tr" elements). In this case the selector chooses the last "tr" for the p:selectOneRadio's table, rather than the p:datatable.
Not a problem, but the statement can be shortened to exclude the each() because of jQuery's implicit iteration.
What I ended up with was:
oncomplete="jQuery('#tableForm\\:table .ui-datatable-data > tr').last().find('span.ui-icon-pencil').click();"
This selector says - get the last "tr" element, which is a direct child of an element with class ".ui-datatable-data", which is also a descendant of the element with id "table" in form "tableForm". In other words you can now have multiple p:datatables, and any include any components that render html tables.
Try this :
jQuery('#FormID\\:DataTableID\\:#{datatable.size()}\\:rowEditorID').find('span.ui-icon-pencil').each(function(){jQuery(this).click()});
worked well, no matter how many datatables in a same page.
If you have several DataTable which each of them has an ID, then try to use one of these solutions:
Oncomplete="jQuery('#FrmID:TabViewI:mydataTableID'.replace(/:/g,'\\:')).find('span.ui-icon-pencil').each(function(){jQuery(this).click()});"
OR:
oncomplete="jQuery('#FrmID\\:TabViewID\\:mydataTableID').find('span.ui-icon-pencil').each(function(){jQuery(this).click()});"
This should work perfectly.
Execute a JQuery script on complete process :
oncomplete="editNewRow()"
<script type="text/javascript">
$(document).on("keydown", ".ui-cell-editor-input input", function(event) {
if (event.keyCode == 13) {
$(this).closest("tr").find(".td-edition .ui-row-editor .ui-row-editor-check .ui-icon-check").click();
return false;
}
});
function editNewRow() {
$("#pim\\:invoiceRuleCretariaTable tbody:first tr:first .td-edition .ui-row-editor .ui-icon-pencil").click();
}
</script>
The first function submit the addition action by press on "Enter" key
Execute a JQuery script on complete process :
oncomplete="editNewRow()"
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).on("keydown", ".ui-cell-editor-input input", function(event) {
if (event.keyCode == 13) {
$(this).closest("tr").find(".td-edition .ui-row-editor .ui-row-editor-check .ui-icon-check").click();
return false;
}
});
function editNewRow() {
$("#panel\\:carTable tbody:first tr:last .td-edition .ui-row-editor .ui-icon-pencil").click();
}
</script>
The first function submit the addition action by press on "Enter" key
To solve this is better to use styleClass and because for fix this it is necessary to use javascript, you need to check the html tags in your browser, because it seems that they change with the versions of primefaces. For vesion 6.1 I've put this on my bean:
RequestContext requestContext = RequestContext.getCurrentInstance();
requestContext.execute("$('.styleEventosPlanPrestacion tbody.ui-datatable-data tr:first-child td div.ui-row-editor a.ui-row-editor-pencil').click()");
and In my .xhtml I've put this:
<p:dataTable ... styleClass="styleEventosPlanPrestacion">

Select Item from many menu

Ok I have a simple many menu in wich I call a listener
<p:selectManyMenu style="width: 100%;" id="cmbsectores" valueChangeListener="#{mbcompletado.removeItem}">
<f:selectItems value="#{mbcompletado.sectores}"/>
<f:ajax update="#this"/>
</p:selectManyMenu>
I am looking the way I can use the ValueChangeEvent pass as parameter to detect which item was selected??
So I can use my business logic!
Do i need to use ajax tag? I found an itemSelect event in primeface, framework which I am using, but it only works on charts components!
Thanks in advance
Since you are already using PrimeFaces use p:ajax instead of f:ajax. The event is already set to the appropriate event (valueChanged).
To detect the selected values of the selectManyMenu the value attribute is necessary:
<p:selectManyMenu style="width: 100%;" id="cmbsectores"
value="#{mbcompletado.selectedSectores}">
<f:selectItems value="#{mbcompletado.sectores}"/>
<p:ajax/>
</p:selectManyMenu>
You can remove the valueChangeListener listener altogether.
For a more complete example see SelectManyMenu.
EDIT:
In your backing bean mbcompletado.selectedSectores should point to a collection of the same type like your mbcompletado.sectores. For example, if your sectores is a List of TypeA, selectedSectores should be also a List of the same type (TypeA).
Similar backing-bean structure can be found in the following example SelectManyCheckbox.
You need the <f:ajax listener> (or in this case better <p:ajax listener>) method instead. The ValueChangeListener serves an entirely different purpose and should only be used when you're really interested in both the old and new value, not when you're only interested in the new value.
E.g.
<p:selectManyMenu value="#{bean.selectedSectors>
<f:selectItems value="#{bean.availableSectors}"/>
<p:ajax listener="#{bean.selectedSectorsChanged}" />
</p:selectManyMenu>
with
private List<String> selectedSectors;
private List<String> availableSectors;
public void selectedSectorsChanged() {
System.out.println("Selected sectors are: " + selectedSectors); // Look, JSF has already set it.
// ...
}
See also:
When to use valueChangeListener or f:ajax listener?

Get id of parent naming container in template for in render / update attribute

I have a template and in its Definition I use several forms and buttons.
The problem is the definition (define) xhtml file does not know the component hierarchy.
And for example I want to update the element "table2" in a different form in the same define file.
Template Insert:
<p:tabView id="nav"> <!-- nav -->
<ui:insert name="content_nav">content navigation</ui:insert>
</p:tabView>
defines the first level of my hierarchy "nav"
Template define:
<ui:define name="content_nav">
<h:form id="form1"> <!-- nav:form1 -->
<h:dataTable id="table1"/> <!-- nav:form1:table1 -->
<p:inputText value="#{bean.value}"/>
<p:commandButton action="..." update="nav:form2:table2"/>
</h:form>
<h:form id="form2">
<h:dataTable id="table2"/> <!-- nav:form2:table2 -->
<!-- other elements -->
</h:form>
</ui:define>
In my define part I don't want to know "nav"!
How can I do this? or how can I move one naming component upwards?, or save the highest parent complete id in a variable?
sometimes i saw something like:
update=":table2"
But I could not find any informations about this?, the JavaEE 6 documentation just mentions the # keywords.
Ugly, but this should work out for you:
<p:commandButton action="..." update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2" />
As you're already using PrimeFaces, an alternative is to use #{p:component(componentId)}, this helper function scans the entire view root for a component with the given ID and then returns its client ID:
<p:commandButton action="..." update=":#{p:component('table2')}" />
ugly answer works well
update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2
mainly more useful updating from opened dialog to parent datatable
You may use binding attribute to declare EL variable bound to JSF component. Then you may access absolute client id of this component by using javax.faces.component.UIComponent.getClientId(). See example below:
<t:selectOneRadio
id="yourId"
layout="spread"
value="#{yourBean.value}"
binding="#{yourIdComponent}">
<f:selectItems value="#{someBean.values}" />
</t:selectOneRadio>
<h:outputText>
<t:radio for=":#{yourIdComponent.clientId}" index="0" />
</h:outputText>
Try this:
<h:commandButton value="Click me">
<f:ajax event="click" render="table" />
</h:commandButton>
Additionally to the solutions above I had the problem, that I had to dynamically generate the to-be-updated components (many) based on server-side logic (with maybe harder to find out nesting).
So the solution on the server-side is an equivalent to update=":#{p:component('table2')}"1 which uses org.primefaces.util.ComponentUtils.findComponentClientId( String designId ):
// UiPnlSubId is an enum containing all the ids used within the webapp xhtml.
// It could easily be substituted by a string list or similar.
public static String getCompListSpaced( List< UiPnlSubId > compIds ) {
if ( compIds == null || compIds.isEmpty() )
return "" ;
StringBuffer sb = new StringBuffer( ":" ) ;
for ( UiPnlSubId cid : compIds )
sb.append( ComponentUtils.findComponentClientId( cid.name() ) ).append( " " ) ;
return sb.deleteCharAt( sb.length() - 1 ).toString() ; // delete suffixed space
}
called via some other method using it, e.g. like ... update="#{foo.getCompListComputed( 'triggeringCompId' )}".
1: first I tried without too much thinking to return public static String getCompListSpaced0() { return ":#{p:component('table2')}" ; } in an ... update="#{foo.getCompListSpaced0()} expression, which of course (after thinking about how the framework works :) ) is not resolved (returned as is) and may cause the issues with it some users experienced. Also my Eclipse / JBoss Tools environment suggested to write :#{p.component('table2')} ("." instead of ":") which did not help - of course.

Resources