Prevent <ui:repeat> from being inserted in generated html - jsf

I'm trying to combine JSF2.2 with bootstrap 3.2.0 components and got stuck when trying to use the button group with a dynamically generated list of labels. I traced the problem down to the ui:repeat tag being included in the generated html and thus preventing the correct css styling of bootstrap.
The xhtml code is:
<div class="btn-group">
<ui:repeat var="role" value="#{editUserView.allRoles}">
<button class="btn btn-success" type="button">#{role.name}</button>
</ui:repeat>
</div>
and the out put html is this:
<div class="btn-group">
<ui:repeat><button class="btn btn-success" type="button">Label1</button></ui:repeat>
<ui:repeat><button class="btn btn-success" type="button">Label2</button></ui:repeat>
<ui:repeat><button class="btn btn-success" type="button">Label3</button></ui:repeat>
<ui:repeat><button class="btn btn-success" type="button">Label4</button></ui:repeat>
<ui:repeat><button class="btn btn-success" type="button">Label5</button></ui:repeat>
</div>
Is there a way to prevent the JSF tag from the xmlns:ui="http://xmlns.jcp.org/jsf/facelets namespace being printed in the generated html WITHOUT having to write custom components?
Update
Just for curiosity, the buttons are being displayed as normal buttons (with spacing in between them) and not as desired in the group button all together style.

This is recognizable as Mojarra issue 2900 which was fixed in 2.2.2. It's currently already at 2.2.8. So, just upgrading Mojarra to latest version should do.
That said, the <ui:repeat> is not a taghandler, but a true UI component. I fixed your question title. The <c:forEach> is a true taghandler. See also JSTL in JSF2 Facelets... makes sense? for the difference.

Related

Control generated ID of ui:repeat

Sorry for the simple question. I am learning to use JSF 2.2 to create a form and trying to keep it close to plain HTML5 as possible. I have an ui:repeat generated list that goes like this:
<ul id="nameLst">
<ui:repeat var="d" value="#{controller.names}" varStatus="status">
<li>
<input
jsf:id="nameTxt"
jsf:binding="#{nameTxt}"
jsf:value="#{d}"
type="hidden" />#{d}
</li>
</ui:repeat>
</ul>
It gets rendered like this:
<ul id="nameLst">
<li>
<input id="j_idt14:0:nameTxt" name="j_idt14:0:nameTxt" value="Name1" type="hidden">
Name1
</li>
<li>
<input id="j_idt14:1:nameTxt" name="j_idt14:1:nameTxt" value="Name2" type="hidden">
Name2
</li>
</ul>
Now, I am trying to add names using JavaScript only to this list. Problem is, how can I control this generated id, so I can use it in JavaScript. And mainly, if the list starts empty, how do I generate this id so it can be correctly posted back to the managed bean.
how can I control this generated id, so I can use it in JavaScript
Just give it a fixed id.
<ui:repeat id="names" ...>
Alternatively, use jsfc attribute to turn <ul> into an <ui:repeat>.
<ul id="names" jsfc="ui:repeat" value="#{bean.names}" var="name">
<li>
<input jsf:id="name" type="hidden" value="#{name}" />
</li>
</ul>
And mainly, if the list starts empty, how do I generate this id so it can be correctly posted back to the managed bean
Use JSF for this instead of JS. An example can be found here: How to dynamically add JSF components
See also:
How can I know the id of a JSF component so I can use in Javascript
JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used

Show error messages of fields in a popup after submit

I am trying to open a popup using the below code in jsf.
Forgot password
<div class="modal fade" jsf:id="forgotPassword">
<div class="modal-dialog">
<form jsf:id="reset-password-form">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Request for new password</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="inputEmail">EmailId</label>
<div class="col-sm-9">
<input type="text" class="form-control" jsf:id="inputEmail"
jsf:value="#{myBean.passwordResetEmail}"
name="inputEmail" />
<h:message for="inputEmail" />
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button class="btn btn-primary"
jsf:action="#{myBean.resetPassword}">sendPassword</button>
</div>
</div>
</form>
</div>
</div>
I am facing some issues here.
When the user enters wrong email Id, the user shall be on same page and errors shall be shown. But I see, the popup closes automatically when the invalid emailId is entered.
I also want to display success messages as well.
Can any one help me how to do that.
When the user enters wrong email Id, the user shall be on same page and errors shall be shown. But I see, the popup closes automatically when the invalid emailId is entered.
You're indeed synchronously submitting the form and performing a full page reload. It's exactly that full page reload which causes an apparent "automatically close" of the dialog (it's actually not closed, it's just exactly like you're pressing F5 in browser directly after opening the dialog). You need to submit the form asynchronously and only perform a partial reload.
You can do that by simply enclosing <f:ajax> in the UICommand component, exactly like shown for <h:commandButton> in the average JSF tutorial (which your <button jsf:action> passthrough element ultimately get converted to).
<button ... jsf:action="#{myBean.resetPassword}">
<f:ajax execute="#form" render="#form" />
</button>
Both execute and render attributes indicate in this particular example that the entire form must be processed, and that only the form itself must be partially updated. As long as the form is inside the modal dialog, and not outside, then this will keep the modal dialog open (at least, in the HTML DOM tree).
I also want to display success messages as well.
Just add a (global) faces message in action method.
public void resetPassword() {
// ...
FacesMessage message = new FacesMessage("Some success message");
FacesContext.getCurrentInstance().addMessage(null, message);
}
<h:messages globalOnly="true" />
A null client ID indicates a global faces message and those will only be shown when globalOnly="true" is set.

RequestScoped JSF CDI bean with Bootstrap modal

I am using JSF 2.0 with a Bootstrap 3 framework. Everything seems to be working fine, but I get problems when I want to populate forms in a Bootstrap modal from a RequestScoped CDI bean. It seems to me, after debugging, that the bean is instantiated when the page the modal is in loads, and not when the modal is opened. So, when I then open the modal, the bean does not exist anymore. Here is some of my code:
This is where I open the modal
<li><span class="glyphicon glyphicon-edit"></span> Rediger bruker</li>
This is the modal content, which is on the same page. farmer is the name of bean
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Endre bruker</h4>
</div>
<div class="modal-body">
<div class="well">
<ul class="nav nav-tabs">
<li class="active">Profil</li>
<li>Passord</li>
<li>Referanseperson</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="profile">
<h:form class="form-horizontal form-group">
<fieldset>
<div class="input-group">
<h:outputText id="email" class="form-control" value="#{farmer.theFarmer.email}"/>
Is there any way to prevent the bean from constructing when the page is loaded, but instead when the actual form is rendered?
Looked around on the internet for a long time, but I cannot seem to find anything that helps me.
You can make the component lazily loaded, so that the content is retrieved on a new HTTP request. Assuming you use something like primefaces, you can use p:fragment. If you use RichFaces you can use a rich:outputPanel. Just make sure both of these are set to be rerendered.
You can also use something low level like a JSF panelGrid, and rerender that based on an AJAX call.

Composite components & ID

I want to implement some javas cript into my JSF composite component, but I have problem with id. My java script with:
document.getElementById("myForm:customerId")
does not work, because the id is wrong. I have JSF composite component:
<composite:implementation>
<div id="element_customer">
<h2 class="element_title">Customer</h2>
<h:form id="myForm">
<h:inputText id="customerId" value="#{cc.attrs.customerId}"/>
</h:form>
</div>
</composite:implementation>
and HTML output is:
<div id="element_customer">
<h2 class="element_title">Customer</h2>
<form id="j_idt44:myForm" name="j_idt44:myForm" method="post" ... >
<input type="hidden" name="j_idt44:myForm" value="j_idt44:myForm" />
<input id="j_idt44:myForm:customerId" ... name="j_idt44:myForm:customerId" />
</form>
</div>
Why is "j_idt44" used in HTML output?
Composite components are NamingContainer components like <h:form>, <h:dataTable>, etc. This allows you to have multiple of them in the same view without conflicting IDs.
You need to give the composite component a fixed ID as well. E.g.
<my:composite id="someId" />
I'd also suggest to use <div id="#{cc.id}"> instead of <div id="element_customer">. It will then become someId with the above example.
Unrelated to the concrete problem, this isn't entirely the right purpose of a composite component. A composite component is intented to be of the same kind of <h:inputText>, etc. You seem to rather want a tag file or maybe an include file. See also When to use <ui:include>, tag files, composite components and/or custom components?

Calling servlet post from jsf in different war

I want to call a Servlet which exists in a different war from my war. When user clicks a button we need to call the post method of the servlet. To implement this I did see an existing example which is slightly different but works in that case.
I am using jsf, so in the jsp there is a h:form with another html form inside of it. Below is the code:
<h:form>
<div id="gform" class="column span-20 append-1">
<h:outputText value="Text." /><br/><br/>
<h:commandLink id="addPaymentButton" styleClass="button" onclick='autorenew();return false;'> <span><h:outputText value="Payment Option"/></span> </h:commandLink>
<a id="noThanksButton" href="#"><span><h:outputText value="No Thanks"/></span></a><br/><br/><br/>
<h:outputText style="color:grey" value="Some text" />
<div> </div>
</div>
<form id="hiddenSubmit" method="post" action="https://localhost.myapp.com/myapp/LoginRouter" >
<input type="hidden" name="redirectUrl" value="/myapp/customers/addNewSavedCCInfo.faces"/>
<input type="hidden" name="jump_message" value="IAmJumpingToCC"/>
<input type="hidden" name="jump_url" value="/premiumServices/myPage.htm"/>
<input id="hiddenSubmitButton" type="submit" name="submit" style="display: none" value='' />
</form>
</h:form>
<script language="javascript">
function autorenew(){
window.alert('In js fnt');
document.hiddenSubmit.getElementById('hiddenSubmitButton').click();
window.alert('In js fnt COMPLETE');
return false;
}
So when the button is clicked, javascript is executed which submits the form to the servlet. However I can see in firebug that the second form which I need to submit does not appear. I am not sure how I can call the post method of a servlet class in a different war. Any ideas welcome, I am really stuck!
Thanks.
As per the HTML specification it's forbidden to nest <form> elements. The (mis)behaviour is browser dependent. Some browsers will send all parameters, some browsers will send only the data of the parent form, other browsers will send nothing.
You want to have a single form here. You can perfectly replace the <h:form> by a plain vanilla HTML <form> with the desired action pointing to the servlet in question.

Resources