How to define form action in JSF? - forms

In order to replace the default Spring security login form I came up with this solution:
<form name="f" action="../j_spring_security_check" method="POST" >
<h:panelGrid columns="2">
<h:outputText value="Username" />
<h:inputText id="j_username" />
<h:outputText value="Password" />
<h:inputText id="j_password" />
</h:panelGrid>
<h:commandButton value="Login" />
</form>
But instead of plain <form> tag I would like to use <h:form> since Primefaces components only work within <h:form>. Using <h:form> the form action will be set automatically by JSF to the current page, not to the value set by me in the example above. Where to I have to code the action "../j_spring_security_check" now? I tried putting it into the <h:commandButton> as follows but that doesn't work:
<h:form name="f">
<h:panelGrid columns="2">
<h:outputText value="Username" />
<h:inputText id="j_username" />
<h:outputText value="Password" />
<h:inputText id="j_password" />
</h:panelGrid>
<h:commandButton value="Click here" action="../j_spring_security_check" />
</form>
It leads to the error message Unable to find matching navigation case with from-view-id '/login.xhtml' for action '../j_spring_security_check' with outcome '../j_spring_security_check'.
Is it the only way to define a navigation case in faces-config.xml? I want to avoid using a bean for this simple use case.

The best solution for me is to use the default <button> tag instead. Since typical button styling is not being applied (in my case I am using Primefaces), I set it manually. Here's the whole result:
<h:outputStylesheet library="primefaces" name="jquery/ui/jquery-ui.css" />
<h:outputStylesheet library="css" name="login.css" />
<div class="message">
<c:if test="#{param.error == 1 and SPRING_SECURITY_LAST_EXCEPTION != null}">
<span class="error">#{SPRING_SECURITY_LAST_EXCEPTION.message}</span>
</c:if>
</div>
<div class="login">
<form action="../j_spring_security_check" method="post">
<h:panelGrid columns="2">
<h:outputText value="Username" />
<h:inputText id="j_username" />
<h:outputText value="Password" />
<h:inputSecret id="j_password" />
</h:panelGrid>
<div class="submit">
<button type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
<span class="ui-button-text">Login</span>
</button>
</div>
</form>
</div>

<h:form id="login" prependId="false" onsubmit="document.getElementById('login').action='j_security_check';">

Your action attribute should be an EL expression like follows:
action="#{managedBean.method}"

Your best chance is to use the onclick property of the button. This is an example with a primefaces commandButton, but it will also work for jsf components because it uses the (native) javascript onclick function.
<h:form>
<p:commandButton value="Submit" onclick="alert('JS!')" actionListener="#{tweetBean.addTweet()}" update=":tabView,:trends,:tweetsnr" />
</h:form>

Related

How to send data from input using asp-route attribute?

I'm using this code to call controller with action.
I want to send data from input tag inside asp-route-data.
<span><label><b>Korisnik :</b></label></span>
<br />
<input type="text" name="korisnik" id="korisnik" size="40" height="25" />
<br />
<br />
<span><label><b>Lozinka :</b></label></span>
<br />
<input type="password" name="lozinka" id="lozinka" size="40" height="25" />
<br />
<br />
<button type="submit" title="Login" class="btnLogin" asp-controller="Members" asp-route-username=a sp-route-password="" asp-action="LoginUser">
So, asp-route-username should be the value from input korisnik.
Is it possible?
If I understood your question correctly (of which I'm not so sure) I think the answer to your problem is it use <form> tag. Then instead of appling the asp-route attributes on <button> tag, apply them on <form> tag:
<form asp-controller="Members" asp-action="LoginUser" asp-route-username="a" asp-route-password="">
<span><label><b>Korisnik :</b></label></span>
<br />
<input type="text" name="korisnik" id="korisnik" size="40" height="25" />
<br />
<br />
<span><label><b>Lozinka :</b></label></span>
<br />
<input type="password" name="lozinka" id="lozinka" size="40" height="25" />
<br />
<br />
<button type="submit" title="Login" class="btnLogin"></button>
</form>
Be sure to check out the official ASP.NET Core documentation on how to work with forms.
If you pass username and password using asp-route-{value}, it will show these information in the url which is not recommended.
If you just want to pass the two input values from view to controller, you need to modify name attribute of input to match the action parameters.For example:
View:
<form method="post" asp-controller="Members" asp-action="LoginUser">
<span><label><b>Korisnik :</b></label></span>
<br />
<input type="text" name="username" id="korisnik" size="40" height="25" />
<br />
<br />
<span><label><b>Lozinka :</b></label></span>
<br />
<input type="password" name="password" id="lozinka" size="40" height="25" />
<br />
<br />
<button type="submit" title="Login" class="btnLogin"></button>
</form>
Action:
[HttpPost]
public async Task<IActionResult> LoginUser(string username,string password)

JSF Updating forms

I am trying to submit some data in JSF. The problem is that I have two forms and the button which I want to trigger the update is outside of the forms, here I place my code so that you can understand better what I mean. Because of that I cannot submit any data to the server.
<ui:define name="mainArea">
<h:form id="form">
<div class="row">
<div class="col-md-5">
<p:outputLabel for="rfqName" value="Name" />
<br></br>
<p:inputText id="rfqName" required="true" style="width:100%;"
value="#{data.data.rfqName}" maxlength="100">
<p:ajax event="change" update="#form"/>
</p:inputText>
</div>
</div>
<div class="row">
<div class="col-md-3">
<p:outputLabel for="rfqVersion" value="Version" />
<br></br>
<p:inputText id="rfqVersion" required="true" style="width:60%;"
value="#{data.data.rfqVersion}" maxlength="20"></p:inputText>
</div>
</div>
</h:form>
</ui:define>
<ui:define name="actionSection">
<p:commandButton actionListener="#{logic.close}" value="Proceed" update=":form"
styleClass="pull-right">
</p:commandButton>
<p:commandButton value="Save" styleClass="pull-right" />
</ui:define>
You can use the primefaces RemoteCommand. This allows you to click the button on the form from the outside.
<ui:define name="mainArea">
<h:form id="form">
<div class="row">
<div class="col-md-5">
<p:outputLabel for="rfqName" value="Name" />
<br></br>
<p:inputText id="rfqName" required="true" style="width:100%;"
value="#{data.data.rfqName}" maxlength="100">
<p:ajax event="change" update="#form" />
</p:inputText>
</div>
</div>
<div class="row">
<div class="col-md-3">
<p:outputLabel for="rfqVersion" value="Version" />
<br></br>
<p:inputText id="rfqVersion" required="true" style="width:60%;"
value="#{data.data.rfqVersion}" maxlength="20"></p:inputText>
</div>
</div>
<p:remoteCommand name="remoteClose" actionListener="#{logic.close}"
update=":form" styleClass="pull-right" />
<p:remoteCommand name="remoteSave" value="Save"
styleClass="pull-right" />
</h:form>
</ui:define>
<ui:define name="actionSection">
<p:commandButton type="button" onclick="remoteClose()" value="Proceed" />
<p:commandButton type="button" onclick="remoteSave()" value="Save"
styleClass="pull-right" />
</ui:define>

JBoss/RichFaces: Action not called if first selectOneMenu in DataTable is empty

I have a problem with richfaces page on JBoss. The page contains (among other things) a list of projects that are to be closed. Before the project can be closed a reason has to be selected. Not all projects need to be filled out. The ones that are left blank are not closed and remain in the table.
Now the problem: If the first row is left blank (no matter which other rows are filled out), the page reloads but the function specified as action on the command button (adminInformationBean.startClosingProjects()) is never called. If a reason is selected at least for the first row, everything is working fine.
This is the xhtml file:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.org/schema/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
template="/layout/template.xhtml"
xmlns:a4j="http://richfaces.org/a4j">
<ui:define name="body">
<div id="cku1405090004">
<h:form id="uma1407080001">
<div>
<rich:panel styleClass="PanelHeader">
<f:facet name="header">
#{messages.adminInfo_table_header}
</f:facet>
<rich:tabPanel id="myTabPanelAdminInfo" styleClass="PanelHeader">
[...]
<!-- closed Projects -->
<rich:tab id="closedProjects">
<f:facet name="header">#{messages.adminInfo_table_type_close}
<h:outputText value="#{adminInformationBean.closedProjectsSize}"/>
</f:facet>
<div class="actionButtons">
<div class="ViewButtonLeft" />
<h:commandButton id="cku1405090011" styleClass="ViewSubmitButtonBody" value="#{messages['adminInfo_table_button_check']}" action="#{adminInformationBean.startClosingProjects()}" onclick="doPostBack();"/>
<div class="ViewButtonRight" />
</div>
<rich:dataTable id="closedProjectsTableId" styleClass="rich-datatable" value="#{adminInformationBean.infoListClosedProjects}" var="adminInfo" iterationStatusVar="iterator" rows="#{adminInformationBean.selectedItem}" rowKeyVar="row" rowClasses="ViewOddLine, ViewEvenLine">
<f:facet name="noData">#{messages.team_table_filter_message}</f:facet>
<f:facet name="header">
<rich:columnGroup>
<rich:column>
<span>
<h:outputText value="#{messages.adminInfo_table_header_projectName} " />
</span>
</rich:column>
<rich:column>
<span>
<h:outputText value="#{messages.adminInfo_table_header_reason}" />
</span>
</rich:column>
</rich:columnGroup>
</f:facet>
<rich:column filterValue="#{filterBean.projectNameFilter}" filterExpression="#{fn:containsIgnoreCase(adminInfo.projectName, filterBean.projectNameFilter)}">
<f:facet name="header">
<h:panelGroup>
<h:inputText id="projectNameClose" value="#{filterBean.projectNameFilter}">
<a4j:ajax render="closedProjectsTableId#body, tgrid2Id4#body" execute="#this" event="keyup" />
</h:inputText>
</h:panelGroup>
</f:facet>
<span>
<h:outputText value="#{adminInfo.projectName}" rendered="#{adminInfo.projectName != null}"/>
</span>
</rich:column>
<rich:column>
<div align="center">
<h:selectOneMenu class="selectReason" value="#{adminInfo.reason}">
<s:selectItems value="#{adminInformationBean.possibleReasons}" var="reason" label="#{reason.name}" itemValue="#{reason.id}" noSelectionLabel="" />
</h:selectOneMenu>
</div>
</rich:column>
</rich:dataTable>
<h:panelGrid id="tgrid2Id4" columns="3">
#{messages.team_table_rows_selectonemenu}
<h:selectOneMenu value="#{adminInformationBean.selectedItem}" onchange="submit()" valueChangeListener="#{adminInformationBean.pageSizeValueChanged}">
<f:selectItems value="#{adminInformationBean.selectItemsMap}"/>
</h:selectOneMenu>
<rich:dataScroller for="closedProjectsTableId" page="#{adminInformationBean.page}" maxPages="" fastControls="hide">
<f:facet name="first">
<h:outputText value="<<"/>
</f:facet>
<f:facet name="previous">
<h:outputText value="<"/>
</f:facet>
<f:facet name="next">
<h:outputText value=">"/>
</f:facet>
<f:facet name="last">
<h:outputText value=">>"/>
</f:facet>
</rich:dataScroller>
</h:panelGrid>
<div class="actionButtons" style="padding-bottom: 20px">
<div>
<div class="ViewButtonLeft" />
<h:commandButton id="cku1405090012" styleClass="ViewSubmitButtonBody" value="#{messages['adminInfo_table_button_check']}" action="#{adminInformationBean.startClosingProjects()}" onclick="doPostBack();"/>
<div class="ViewButtonRight" />
</div>
</div>
</rich:tab>
[...]
</rich:tabPanel>
</rich:panel>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>

JSF <f:validator> and Bootstrap do not work together

I am trying to get my JSF Register form working with Bootstrap styles. Everything works fine, but i do not know how i can integrate my validation messages into my form. If i render this code the validation messages are just ignored. I don't know why? Any idea how i can make them visible and maybe style them good-looking? Many thanks in advance for your help!
<!-- Register Form -->
<h:form role="form" style="width: 400px; margin: 0 auto;">
<!-- User name -->
<div class="required-field-block">
<h:outputLabel for="name" value="Benutzername"></h:outputLabel>
<h:inputText id="name" value="#{userBean.user.name}"
validatorMessage="gültigen Benutzernamen mit 4-116 Zeichen" class="form-control">
<f:validateLength minimum="4" maximum="16" for="name"></f:validateLength>
</h:inputText>
<div class="required-icon">
<div class="text">*</div>
</div>
</div>
<!-- Password -->
<div class="required-field-block">
<h:outputLabel for="password" value="Passwort"></h:outputLabel>
<h:inputSecret id="password" value="#{userBean.user.password}"
class="form-control" required="true"
requiredMessage="Mailadresse angeben">
</h:inputSecret>
<div class="required-icon">
<div class="text">*</div>
</div>
</div>
<!-- Email -->
<div class="required-field-block">
<h:outputLabel for="email" value="Email"></h:outputLabel>
<h:inputText id="email" value="#{userBean.user.email}"
class="form-control" required="true"
requiredMessage="Passwort angeben">
<!-- Email Validation -->
<f:validator validatorId="emailValidator"></f:validator>
</h:inputText>
<div class="required-icon">
<div class="text">*</div>
</div>
</div>
<!-- Age -->
<div>
<h:outputLabel for="age" value="Alter"></h:outputLabel>
<h:inputText id="age" value="#{userBean.user.age}" class="form-control"></h:inputText>
<h:message for="age"></h:message>
</div>
<h:commandButton id="send" value="Register" type="submit"
action="#{userBean.addUser}" class="btn btn-primary"></h:commandButton>
<h:message for="send"></h:message>
<h:commandButton id="reset" value="Reset" type="submit"
action="#{userBean.reset}" immediate="true" class="btn"></h:commandButton>
<h:message for="send" errorClass="errorMessage" globalAll="true"></h:message>
</h:form>
Just use jsf tag <h:message/> under each required input with attribute for where you should point input's id.
Also for good-looking style you can add bootstrap class "text text-danger". Also you can use attribute label for <h:inputText>.
It means you will get following error:
Email:Validation Error
instead of
email-id: Validation error.
For example:
<h:outputLabel for="email" value="Email"></h:outputLabel>
<h:inputText id="email-id" label="Email" value="#{userBean.user.email}"
class="form-control" required="true"
requiredMessage="Passwort angeben">
<!-- Email Validation -->
<f:validator validatorId="emailValidator"></f:validator>
</h:inputText>
<h:message for="email-id"/>

How can I prevent p:commandButton to refresh p:tabView

my xhtml page has this format:
<h:form>
<p:dialog widgetVar="presentDiag" modal="true" closable="true" header="Liste" maximizable="false" dynamic="true">
<p:commandButton value="Submit" id="submit" actionListener="bean.add()"/>
</p:dialog>
</h:form>
<h:form>
<p:tabView>
<p:tab title="....">
</p:tab>
<p:tab title="....">
</p:tab>
<p:tab title="....">
</p:tab>
</p:tabView>
</h:form>
when I click on the submit button the selected tab changed to the first tab
If you wanted to update a form and then exclude something from it, the easiest way would be to use PrimeFaces selectors like so :
<h:form id="form">
<p:dialog widgetVar="presentDiag" modal="true" closable="true" header="Liste" maximizable="false" dynamic="true">
<p:commandButton value="Submit" id="submit" actionListener="bean.add()" update="#(form :not(.tab-view))"/>
</p:dialog>
<h:panelGroup styleClass="tab-view" >
<p:tabView>
<p:tab title="....">
</p:tab>
<p:tab title="....">
</p:tab>
<p:tab title="....">
</p:tab>
</p:tabView>
</h:panelGroup>
</h:form>
you can always reopen a desired tab by using widgetVar attribute.
<p:tabView widgetVar="myTab"> .... </p:tabView>
.
.
.
<p:commandButton value="Submit" id="submit" actionListener="bean.add()" update="someId" oncomplete="myTab.select(2);"/>
but the best thing to do would be not closing it in the first place.