I have a search bar with a Dropdown (for user to choose) and an Input Text to display details of a data.
The flow is like this;
The user will pick either one of the two options from the dropdown (Range Id, Awb)
User then have to enter an ID in the inputText and then click on the searchButton which go to doSearch to eventually display the details of the entered ID on screen.
If the ID I entered are valid, I am able to view the respective pages. However, I notice that when the first ID is invalid, it gives back the correct invalid message (idNotValid.show()) but after that when I change the value of dropdown without refreshing the page, the dropdown value is not updated and doesn't refresh/restart the whole process of doSearch.
Navigation.xhtml
<h:panelGroup>
<h:selectOneMenu id="option" value="#{viewRangeClassBean.selectOption}" style="width:80px">
<f:selectItem itemLabel="Range ID" itemValue="A" />
<f:selectItem itemLabel="Awb" itemValue="B" />
</h:selectOneMenu>
<p:inputText id="search" value="#{viewRangeClassBean.rangeId}" style="width:100px"
onkeypress="if (event.keyCode == 13) {
document.getElementById('navigationForm:searchButton').click();} "
converterMessage="#{msg['Dims.numericConverterMsg']}"></p:inputText>
<p:commandButton value="#{msg['.GoButton']}" id="searchButton" action="#
{viewRangeClassBean.doSearch}" oncomplete="if(args.ridNotFound){ridNotFound.show()} else
if(args.idNotFound){idNotFound.show()} else if(args.idNotValid){idNotValid.show()}" />
</h:panelGroup>
ViewRangeClassBean.java
public String doSearch() throws DimsApplicationException {
Long rangeIdLong;
// Check for input range and option selected
if (null != rangeId) {
if ("A".equals(selectOption)) {
// search by complete id
try {
rangeIdLong = Long.parseLong(rangeId);
} catch (NumberFormatException e) {
RequestContext.getCurrentInstance().addCallbackParam("idNotValid", true);
return "null";
}
return searchRangeId(rangeIdLong);
} else if ("B".equals(selectOption)){
// Searching by awb
return searchIdentifier(loginBean.getCurrentIdentifier());
} else {
return null;
}
} else {
return null;
}
}
Related
I have a problem in JSF 2.1: an input text field is bound to a list in a backing bean, when submit the form, if input value is not blank, the list can fetch the new input value; if input value is blank, the list just keep old input value.
Please could anyone tell what the problem is? How to make the list in a backing bean fetch new input value exactly ?
JSF code:
<h:form id="the-form">
<ui:repeat value="#{myBean.listDate}" var="a" varStatus="aStatus">
<h:outputLabel value="input date" />
<h:inputText value="#{a}" valueChangeListener="#{myBean.onChangeCTDate}" >
<f:ajax event="change" execute="#this" listener="#{myBean.onChangeCTDate}" />
</h:inputText>
</ui:repeat>
<h:commandButton id="btnValidate" value="validate" action="#{myBean.onValidate}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
</h:form>
Bean code:
#ManagedBean(name = "myBean")
#SessionScoped
public class MyBean {
public void onChangeCTDate(ValueChangeEvent vce) throws SQLException {
String s = (String) vce.getNewValue();
System.out.println("new Value = " + s);
}
public void onChangeCTDate(AjaxBehaviorEvent e) throws SQLException {
Object val = ((UIInput) e.getSource()).getValue();
System.out.println("Value = " + val);
}
public void onValidate() {
System.out.println("---list begin---");
for (String item : listDate) {
if (item == null) {
System.out.println("Value = " + item);
} else {
System.out.println("Value = " + item);
}
}
System.out.println("---list end---");
}
}
Here is an example of runtime situation:
Open the above page,
click button "validate",
input value then click button "validate",
clear input value then click button "validate".
Runtime console display:
---list begin---
Value =
---list end---
new Value = 07/04/2021
Value = 07/04/2021
---list begin---
Value = 07/04/2021
---list end---
new Value = null
Value = 07/04/2021
new Value = null
---list begin---
Value = 07/04/2021
---list end---
I'm working an inherited JSF app. Still quite new to it.
Here's a screenshot of the page I'm working with: http://goo.gl/GidpCD. This is some exam software and what you're looking at is question administration. On this screen the user can write the question, cite the question source, write answers, associate to a category and associate images.
Where I'm getting stuck is when I add/delete answers down toward the bottom.
I'm suspicious that my issue is with ViewState.
When I click the add or delete answers. The page reloads and I lose my file associations within a JSF dataTable component. ViewState is maintained in all of the other form elements on the page, it's just those files within that dataTable that I can't seem to get my head wrapped around. Here's that JSF dataTable component (I'll list the code in it's entirety below):
<h:dataTable id="table0" value="#{adminQuestions.filesList}" var="file" columnClasses="id,title,selected last" rendered="true" >
<h:column>
<f:facet name="header">File</f:facet>
<h:graphicImage value="#{file.path2}" alt="" />
</h:column>
<h:column>
<f:facet name="header">Title</f:facet>
<h:outputText value="#{file.title}" />
</h:column>
<h:column>
<f:facet name="header">Select files</f:facet>
<h:selectBooleanCheckbox value="#{file.selected}" />
</h:column>
</h:dataTable>
Here's the JSF button compnent to fire the add add answer method:
<h:commandButton value="#{msgs.addButton}" action="#{adminQuestions.addQuestionToAnswerRow}" />
And here's that add answer method:
public String addQuestionToAnswerRow() {
if(this.questionToAnswerList.size() < 8) {
// set the scroll
if(FacesContext.getCurrentInstance().getMessageList().size() > 0) {
this.scroll = false;
}
else {
this.scroll = true;
}
//Create a new answer, set the current question, and add it to the collection
Answers answer_local = new Answers();
QuestionToAnswer qta_local = new QuestionToAnswer();
answer_local.setTitle(this.inputTextAnswer);
answer_local.setDescription(this.inputTextAnswer);
answer_local.setCorrect(this.correctAnswer);
qta_local.setAnswers(answer_local);
qta_local.setAnswer(this.questionToAnswerList.size() + 1);
qta_local.setQuestions(this.question);
this.questionToAnswerList.add(qta_local);
// reset the input fields
this.inputTextAnswer = "";
this.correctAnswer = false;
List<File1> thisFilesList = getFilesList();
QuestionsToFiles qtf;
List<QuestionsToFiles> qtfc = new ArrayList<QuestionsToFiles>();
if(this.filesList != null) {
for(Iterator<File1> entries = this.filesList.iterator(); entries.hasNext();) {
File1 file_temp = entries.next();
if(file_temp.isSelected()) {
qtf = new QuestionsToFiles();
qtf.setQuestions(this.question);
qtf.setFile1(file_temp);
qtfc.add(qtf);
}
}
}
return null;
}
else {
JSFUtils.addErrorMessage("No more than eight answers are allowed: ", "The question cannot have more than eight answers");
return null;
}
}
Here's the JSF button component to fire the delete method
<h:commandButton value="#{msgs.deleteButton}" action="#{adminQuestions.deleteQuestionToAnswerRow(a)}" />
And the delete method:
public String deleteQuestionToAnswerRow(QuestionToAnswer qta_local) {
// set the scroll
if(FacesContext.getCurrentInstance().getMessageList().size() > 0) {
this.scroll = false;
}
else {
this.scroll = true;
}
//Iterate through the category exam collection and delete the associated category so it's reflected on the page
for (Iterator<QuestionToAnswer> itr = this.questionToAnswerList.iterator(); itr.hasNext();) {
QuestionToAnswer qta_temp = itr.next();
if(qta_temp == qta_local) {
qta_temp.setQuestions(null);
qta_temp.setAnswers(null);
itr.remove();
return null;
}
}
return null;
}
Here's a Gist the XHTML page in it's entirety
Here's a Gist the Java class in it's entirety
Thanks for taking a look.
I have one dataTable in my screen. In the column header there is a selectBooleanCheckBox. If I
select it then all the boolean check boxes are get selected and deselected if I deselect the header boolean check box. My datatable is binded is with htmlDatatable. In bean all values are being set but it is not reflected in UI. Kindly help....
<t:dataTable id="physicalAccessDetailsDataTable1" binding="#{bean.htmlDataTable}">
<f:facet name="header">
<h:selectBooleanCheckbox id="selectAll" value="#{bean.editablePhysical}"
valueChangeListener="#{bean.selectAllFromPhysicalDatatable}"
onclick="submit()" />
</f:facet>
here is my bean code...
public String selectAllFromPhysicalDatatable(ValueChangeEvent vcep) {
if (editablePhysical == false) {
System.out.println(editablePhysical);
editablePhysical = true;
for (PhysicalAccessDetail physicalAccessDetail : physicalAccessDetailsList) {
System.out.println("INside loop of true");
physicalAccessDetail.setEditable(true);
}
} else {
editablePhysical = false;
for (PhysicalAccessDetail physicalAccessDetail : physicalAccessDetailsList) {
physicalAccessDetail.setEditable(false);
}
}
return null;
}
I have an input text that have required=true attribute, like below
<h:panelGrid columns=2>
<h:panelGroup id="ccm">
<p:inputText id="txtCCMNumber" value="#{setupView.selectedCCM}"
required="true" requiredMessage="Required">
<p:ajax event="blur" listener="#{setupView.handleLooseFocusCCMTextbox()}"
update=":setupForm:ccm :setupForm:ccmMsg"/>
</p:inputText>
<h:outputText value="Duplicated" id="ccmExisted"
styleClass="ui-message-error ui-widget ui-corner-all"
rendered="#{setupView.ccmNameExisted}"/>
<h:graphicImage id="ccmNotExist" url="resources/images/check-icon.png"
rendered="#{setupView.ccmNameUnique}"
width="18"/>
</h:panelGroup>
<p:message for="txtCCMNumber" id="ccmMsg" display="text"/>
</h:panelGrid>
So my requirement is, if the value is empty, then it will display Required, since required=true, it should fail at Process Validation phase. If the value is unique, then display a check image, if duplicated, then display Duplicated text. The problem that I run into is, after I type something and tab away (let say I type something unique), it displays the check image, I then erase the text, and tab away again, now the Required text appear, but so is the check image. My theory is that, at the Process validation phase, it fail due to the value is empty, so at the update component phase, it does not invoke that method handleLooseFocusCCMTextbox() that will set the boolean ccmNameUnique to false. Is there a way to fix this?
NOTE: handleLooseFocusCCMTextbox() just turn the boolean value on and off to display the check image or Duplicated text.
Answered. Create Validator class, take out required=true
public void validate(FacesContext fc, UIComponent uic, Object value)
throws ValidatorException {
FacesContext context = FacesContext.getCurrentInstance();
SetupView setupView = (SetupView) context.getApplication().
evaluateExpressionGet(context, "#{setupView}", SetupView.class);
if (value == null || value.toString().isEmpty()) {
setupView.setCcmNameUnique(false);
FacesMessage message = new FacesMessage();
message.setSeverity(FacesMessage.SEVERITY_ERROR);
message.setSummary("Error");
message.setDetail("Required");
//This will end up in <p:message>
throw new ValidatorException(message);
}
String rootPath = setupView.getRootPath();
File rootFolder = new File(rootPath);
if (rootFolder.exists() && rootFolder.canRead()) {
List<String> folderNames = Arrays.asList(new File(rootPath).list());
if (folderNames.contains(value.toString())) {
setupView.setCcmNameUnique(false);
FacesMessage message = new FacesMessage();
message.setSeverity(FacesMessage.SEVERITY_ERROR);
message.setSummary("Error");
message.setDetail("Duplicate");
//This will end up in <p:message>
throw new ValidatorException(message);
} else {
setupView.setCcmNameUnique(true);
}
} else {
logger.log(Level.SEVERE, "Please check the root folder path as "
+ "we cannot seems to see it. The path is {0}", rootPath);
}
}
You want to use a validator instead of an action listener.
<p:inputText id="txtCCMNumber" value="#{setupView.selectedCCM}"
required="true" requiredMessage="Required"
validator="#{setupView.validateDuplicateCCM}">
<p:ajax event="blur" update="ccm ccmMsg" />
</p:inputText>
with
public void validateDuplicateCCM(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (value == null || value.toString().isEmpty()) {
return; // Let required="true" handle.
}
// ...
if (duplicate) {
((UIInput) component).setValid(false);
ccmNameExisted = true;
// I'd rather throw ValidatorException instead of above two lines here so that it ends up in <p:message>
} else {
ccmNameUnique = true;
}
}
My question is how can i retrieve selected item in backing bean ?
In my view page i have one select box component :
<h:selectOneMenu id="materialCat"
value="#
{materialMasterBean.materialDTOs.materialCategoryId}" required="true" requiredMessage="Material Category is Mandatory">
<f:selectItem itemLabel="select" itemValue="-1" />
<f:selectItems value="#{materialMasterBean.materialCatList}" />
</h:selectOneMenu>
This is my backing bean
` public ArrayList getMaterialCatList() {
if(materialCatList == null )
{
materialCatList= new ArrayList<SelectItem>();
ArrayList<MaterialDTO> temp;
try {
temp= getAdminDelegate().getMaterialLsit();
for (int i = 0; i < temp.size(); i++)
{
MaterialDTO materialDTO = temp.get(i);
item = new SelectItem(materialDTO.getMaterialCategoryId(),materialDTO.getMaterialCategory());
materialCatList.add(item);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return materialCatList;
}
else
{
return materialCatList;
}
}
`
also in backing Bean i have:
private MaterialDTO materialDTOs;
please help me
you can access it in your bean if you binded it with the value="#{bean.filed} attribute
EDIT: here is an example on how to do a selectonebox, i think you missunderstood some things. Do you want to select a MaterialDTO Object in the list? or an Id? You dont need an ArrayList with SelectItem ...