I'm implementing simple registration form. Table with inputs and labels is placed in p:dialog which is placed in h:form. One of the feature is automatically generated alphanumeric password. I want to update value of password p:inputText after clicking button which is placed in the same form. Generating method is called every time I push the button (and I can see generated strings in console log). The problem is related with the inputText tag which is not updated properly. After opening the dialog box I can refresh password inputText only once, next time method is fired but inputText is not updated. The code is as below:
Alphanumeric password generator method:
public static String randomPassword(){
return RandomStringUtils.randomAlphanumeric(PASSWORD_LENGTH);
}
New account model:
#Named
#ViewScoped
public class AccountModel implements Serializable {
private Account Account = new Account();
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
Password fixing method in ViewScoped AddUserBean:
public void generateRandomPassword() {
accountModel.getAccount().setPassword(PasswordGenerator.randomPassword());
LOGGER.info(MessageFormat.format("Random password generated: {0}", accountModel.getAccount().getPassword()));
}
JSF form snippet:
<p:column>
<p:inputText id="userPassword" value="#{accountModel.account.password}" styleClass="fullWidth" />
</p:column>
<p:column>
<p:commandButton id="randomPasswordButton" update="userPassword">
<p:ajax event="click" listener="#{addUserBean.generateRandomPassword}" update="userPassword" />
</p:commandButton>
</p:column>
The question is: What kind of updating should I use for proper password inputText refreshing (every time I push the button, not only once)?
Related
This question already has answers here:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
(5 answers)
Closed 6 years ago.
I have a modal dialog, where a user can select and deselect roles based on another user and then submit this to the database to be updated.
However, after debugging, the ArrayList that backs the ManyCheckbox doesn't get updated, and the selectedRoles ArrayList remains to what it originally was.
For example:
I load the application
There is one user in the database with role 'admin'
I try to edit this user and the dialog opens up, 'admin' checkbox is selected.
I click the 'user' role checkbox and click submit
The selectedRoles array is still only just 'admin' instead of 'admin' and 'user'
Here is my dialog modal:
<p:dialog header="Editing User ID: #{usersView.viewUser}" id="editUserDialog" widgetVar="editUserDialog" modal="true" appendTo="#(body)">
<h:form id="editUserForm">
<p:selectManyCheckbox id="roleSelect" value="#{usersView.selectedRoles}" layout="grid" columns="3">
<f:selectItems value="#{rolesView.roles}" var="role" itemLabel="#{role.name}" itemValue="#{role.name}" />
</p:selectManyCheckbox>
<p:separator />
<p:commandButton process="#this" update=":form:tabs:adminView:userTable:userRoleOutput" value="Submit" id="EditUserSubmitButton" actionListener="#{usersView.editUserRole}" oncomplete="PF('editUserDialog').hide();" />
</h:form>
</p:dialog>
UserView:
#ManagedBean(name="usersView", eager=true)
#ApplicationScoped
private ArrayList<String> selectedRoles;
public Arraylist<String> getSelectedRoles()
{
return this.selectedRoles;
}
public void setSelectedRoles(ArrayList<String> roles)
{
this.selectedRoles = roles;
}
public void editUserRole(ActionEvent actionEvent)
{
// This method literally just loops through all users and matches the one we're looking at
User user = findUser();
if (user != null)
{
// gives user checked roles in database and local session
addSelectedRoles(user);
ArrayList<String> rolesToRemove = user.getRoleNames();
rolesToRemove.removeAll(selectedRoles);
// removes user unchecked roles in database and local session
removeSelectedRoles(user, rolesToRemove);
}
else
{
// Handle exception...
}
}
I am working on a restricted VM, so I cannot copy and paste and this is all the information I can post, which I believe is enough.
Any help is greatly appreciated.
I solved my issue by removing process="#this" and now the ArrayList is getting updated.
process="#this" means that the current component of the commandLink and hence why it wasn't updating.
I need to build a JSF page with some input form and when click save all this information have to be stored.In particular an input form need to submit a string and then the system makes some check and store or discard the string(for example i need to save an event in my calendar and add some other person).
I tried to use only a view scoped bean but when i call the method to check the string the bean is destroyed, so i change this method to return an empty string and all was fine but when i reload the page the input form are still filled with old information.
How i can reset input or how i can improve my solution.
Thanks for help
After using the value of the fields in your action method, just fill it with a blank value and re render your form. Here's an example:
Facelets code
<h:form>
<h:input value="#{theBean.theString}" />
<h:commandButton value="Submit" action="#{theBean.action}">
<f:ajax render="#form" />
</h:commandButton>
</h:form>
Managed bean code
#ManagedBean
#ViewScoped
public class TheBean {
private String theString;
//getters and setters
public void action() {
//do something with the submitted value of theString
//at the end, clean it manually
theString = "";
}
}
i am developing a java web application using primefaces 4.0 and jsf 2.0.
i have a text label and it's textbox. when user is in edit mode, and want to modify the value of a particular textbox, the old value of the textbox should be displayed on the right side while the user is entering the new value in the textbox. so i add an output text which rendered false on load. i want to trigger this output text(id="test") when the user click in the textbox(id="customer_customername"). so rendered should be change to equal. anyone can tell me how to do this? in my backend i have an interface with its implementation , dao and service.
<h:panelGrid id="detail1" columns="2" styleClass="grid" columnClasses="label,value">
<h:outputText value="#{customermsgs['customer.customername.title']}:" />
<h:inputText id="customer_customername" value="# {CustomerComponent.customer.customername}" onclick="#{CustomerComponent.customername}" label="customer_customername">
<f:ajax render="detail1" />
</h:inputText>
<h:outputText id="test" value="#{CustomerComponent.customer.customername}" rendered="#{CustomerComponent.visible}"/>
</h:panelGrid>
public class CustomerComponentImpl implements CustomerComponent {
/**
* Data type variable that provides CRUD operations for Customer entities
*
*/
private boolean visible=false;
private String customername;
public String getCustomername() {
return customername;
}
public void setCustomername(String customername) {
setVisible(true);
this.customername = customername;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
//some codes goes here.
Note: i have implemented the method in my interface also.
the onclick event is not working. look like it does not trigger! anyone can help?
This,
<h:inputText ... onclick="#{CustomerComponent.customername}">
does very definitely not what you thought it does. In its current form, when filled, it would only cause a JavaScript error because the #{CustomerComponent.customername} does very likely not return a piece of (syntactically valid!) JavaScript code which should be executed on click. Instead, it's more likely to return a string representing the customer name. When printed this into JavaScript context, it would only be interpreted as an undefined JavaScript variable.
As to your concrete functional requirement, the <f:ajax> listens inside input components by default only on change event. You can change this to click by setting the event attribute accordingly. All in all, this should do as you intented:
<h:inputText id="customer_customername" value="#{CustomerComponent.customer.customername}" label="customer_customername">
<f:ajax event="click" render="detail1" />
</h:inputText>
I came up with a strange problem. I tried to isolate the problem so following is my simplified code.
public class MyBean {
private List<Data> dataList;
Data selectedData;
public MyBean() {
dataList = new ArrayList<Data>();
dataList.add(new Data("John", 16));
dataList.add(new Data("William", 25));
}
public List<Data> getDataList() {
return dataList;
}
public void edit(Data data) {
selectedData = data;
}
public void newData() {
selectedData = new Data(null, null);
}
public Data getSelectedData() {
return selectedData;
}
public class Data {
String name;
Integer age;
Data(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
}
xhtml:
<rich:modalPanel id="pop">
<h:form>
Name: <h:inputText value="#{myBean.selectedData.name}" required="true" id="txtName"/><br/>
Age : <h:inputText value="#{myBean.selectedData.age}" required="true" id="txtAge"/>
<a4j:commandButton value="Save"/>
<a4j:commandButton value="Close" onclick="Richfaces.hideModalPanel('pop');return false;"/>
<br/>
<rich:message for="txtName"/><br/>
<rich:message for="txtAge"/>
</h:form>
</rich:modalPanel>
<h:form>
<rich:dataTable value="#{myBean.dataList}" var="data">
<rich:column>#{data.name}</rich:column>
<rich:column>
<a4j:commandLink value="Edit" action="#{myBean.edit(data)}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/>
</rich:column>
</rich:dataTable>
<a4j:commandButton value="New" action="#{myBean.newData()}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/>
</h:form>
This is the path to error:
Load the page
Click the "Edit" link in first row(popup displays)
In popup, clear the "Age" field and click "Save".(Required message shown)
Click cancel(without filling "Age" field)
Click second link.
Now it shows irrelevant data(previous data). - This is the problem
Even when I click "New" button it shows incorrect data.
This happens only if a validation is failed in the popup.
Is there a solution for this?
This problem is in JSF 2 also recognized and explained in detail in the following answer: How can I populate a text field using PrimeFaces AJAX after validation errors occur? If you were using JSF 2, you could have used OmniFaces' ResetInputAjaxActionListener or PrimeFaces' <p:resetInput> or resetValues="true" for this.
To the point, you need to clear the state of the EditableValueHolder component when it's about to be ajax-rendered, but which isn't included in the ajax-execute. To clear the state, in JSF 2 you would have used the convenience method resetValue() for this, but this isn't available in JSF 1.2 and you need to invoke the 4 individual methods setValue(null), setSubmittedValue(null), setLocalValueSet(false), setValid(true) to clear the state.
To figure out which components are to be ajax-rendered, but aren't been ajax-executed, in JSF 2 you would have used PartialViewContext methods for this, but this is not available in JSF 1.2 which hasn't standardized ajax yet. You'd need to fiddle with RichFaces specific ajax API in order to figure that. I can't tell that from top of head, so here's a kickoff example assuming that you already know the components which needs to be cleared. Imagine that the form in your popup has id="popForm" and the name input field has id="nameInput", here's how you could clear it inside the newData() method:
UIInput nameInput = (UIInput) context.getViewRoot().findComponent("popForm:nameInput");
nameInput.setValue(null);
nameInput.setSubmittedValue(null);
nameInput.setLocalValueSet(false);
nameInput.setValid(true);
do one thing on cancel action set all popup values null. now in your next click all values set to be default.
or on click set all previous values null. and set all respective values after that.
I had the same problem. if you are using Primefaces, the solution is as simple as putting resetValues="true" on your p:commandLink or p:commandButton that loads the selected item.
After validation failed if you want to remain same as input data which you have pass as submission parameter, then set value attribute as your form bean name as mention below i.e.
<input type="text" id="fname" path="fname" value="${myFormBean.fname}"/>
I have a JSF page in which I show the details of a given user:
<h:form>
<p>
<h:outputLabel value="User Name" for="userName" />
<h:outputText id="userName" value="#{userController.user.name}" />
</p>
<p>
<h:outputLabel value="Email" for="email" />
<h:outputText id="email" value="#{userController.user.email}" />
</p>
<p>
<h:commandLink value="Edit" action="#{userController.edit(userController.user.id)}" />
</p>
</h:form>
This works fine with the exception of the Edit commandLink. When I click it, I expect userController.edit to be passed the ID of the user that's currently being rendered on the page.
However looks like as userController is a request scoped bean that has a #PostConstruct method that assigns a new User to the user field, always 0 is being passed to the action method as the ID of a new instance of User is null which apparently gets converted to 0.
How can I fix this controller/page, without changing the scope of the controller, to pass the correct ID to the edit action? Here's the code for the controller:
#Model
public class UserController {
#Inject
#UserRepository
private EntityManager entityManager;
#Inject
private UserTransaction tx;
private User user;
public String edit(Long id) {
System.out.println("id = " + id);
// fetch the user with id from the db
return "edit";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#PostConstruct
private void init() {
user = new User();
}
}
The approach is weird but I can imagine when you need this. (e.g. you don't wand to write to session and flash scope don't work in distributed environment etc.). BTW if you can't use session scope consider using flash scope.
Apart from correctness of the approach, try adding aditional field to the bean:
protected Long currentId;
public Long getCurrentId() {
return currentId == null ? user.getId() : currentId;//or simply return it, I don't know how you play with the user field
}
public void setCurrentId(Long currentId) {
this.currentId = currentId;
}
Remove parameter from edit action and use currentId field, and to your view add param (hidden field will not work here):
<f:viewParam name="id" value="#{userController.currentId}" />
Then in action you can get user id from the previous view simply accessing this.currentId.
And BTW, try load your User from another place, not int #PostConstruct. If you create user in #PostConstruct then when you are in edit method the currentId will be from previous view, and user.id will be from #PostConstruct. So if you don't want to store user in session scope, but use only request scope you have to persist it immediately after creation (e.g. in database). In edit method you have to get it back using currentId.