issue with htmlDatatable in jsf 1.2 - jsf

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;
}

Related

Refreshing PrimeFaces form element dataTable (code details provided)

I have Search form. After clicking on Search button data refreshes, but dataTable columns not (columns get refreshed only on second button click). Apparently I am doing something wrong. Dynamic column code is inspired by PrimeFaces Showcase
myForm.xhtml:
<h:form id="MY_FORM">
#{myBean.initBean()}
...
<h:panelGrid id="main">
<h:panelGrid id="buttons">
<p:commandButton id="submitSearch"
value="#{msg['button.execute']}"
actionListener="#{myBean.submitSearch}"
update="resultPanel"/>
</h:panelGrid>
</h:panelGrid>
<h:panelGrid id="resultPanel" border="0">
<p:dataTable id="resultTable" var="result" value="#{myBean.searchResults}">
<p:columns value="#{myBean.columns}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
<h:outputText value="#{column.header}" />
</f:facet>
<h:outputText value="#{result[column.property]}" />
</p:columns>
</p:dataTable>
</h:panelGrid>
</h:form>
I've called column calculation method createColumns() from myBean.initBean() and myBean.submitSearch() with the same result (I see it works correctly from debugger).
#ManagedBean("myBean")
#Scope(value = "session")
public class MyBean {
private ArrayList<HashMap<String,Object>> searchResults;
private List<ColumnModel> columns;
...
public void initBean() {
...
createColumns(selectedDates);
}
public void submitSearch() {
...
ArrayList<HashMap<String, Object>> results = prpRepository.getSearchResultByParams(searchParams);
createColumns(selectedDates);
}
private void createColumns(ArrayList<String> selectedDates){
columns = new ArrayList<ColumnModel>();
columns.add(new ColumnModel("Name", "NAME"));
columns.add(new ColumnModel("Amount", "AMOUNT"));
for (int i = 0; i < selectedDates.size(); i++) {
columns.add(new ColumnModel(selectedDates.get(i), "DATE" + i));
}
setColumns(columns);
}
public List<ColumnModel> getColumns() {
return columns;
}
public void setColumns(List<ColumnModel> columns) {
this.columns = columns;
}
}
Additional information:
I am using:
Oracle's Implementation of the JSF 2.1 Specification
JavaServer Pages API 2.2
Springframework 3.1.2 (incl. spring-context, spring-web)
Glassfish Javax.annotation 3.1.1
The problem is that columns is calculted only once time in the org.primefaces.component.datatable.DataTabe
public List<UIColumn> getColumns() {
// if(columns == null) {
columns = new ArrayList<UIColumn>();
FacesContext context = getFacesContext();
char separator = UINamingContainer.getSeparatorChar(context);
for(UIComponent child : this.getChildren()) {
if(child instanceof Column) {
columns.add((UIColumn) child);
}
else if(child instanceof Columns) {
Columns uiColumns = (Columns) child;
String uiColumnsClientId = uiColumns.getClientId(context);
uiColumns.updateModel(); /* missed code */
for(int i=0; i < uiColumns.getRowCount(); i++) {
DynamicColumn dynaColumn = new DynamicColumn(i, uiColumns);
dynaColumn.setColumnKey(uiColumnsClientId + separator + i);
columns.add(dynaColumn);
}
}
}
// }
return columns;
}
You could comment it and overwrite the class file,
or find the DataTable object and setColumns to NULL inside the createColumns method
Finally I've worked better with debugger and found an answer. Solution was to put createColumns() method call into columns getter getColumns() as it is called automatically before submitSearch(). My problem was in application lifecycle understanding.

Unable to maintain JSF ViewState within a dataTable component

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.

p:pickList doesn't update the source and target

I have been accessing the p:picklist for the first time and I am facing a issue where I am not able to get source and target values updated as in the p:picklist ui. I am using list of DualListModel<String>. Here is the code..
Please help me.
Thanks for the help!
code.xhtml
<p:dataTable value="#{updateSiteObj.dsList}" var="pickListObjDS" >
<p:column headerText="DS">
<p:pickList id="pojoPickListDSID" value="#{pickListObjDS}" var="ds" itemValue="#{ds}" itemLabel="#{ds}" showSourceFilter="true" showTargetFilter="true" filterMatchMode="contains" style="border-color: white!important" onTransfer="ajaxSubmit3()">
<f:facet name="sourceCaption">Available</f:facet>
<f:facet name="targetCaption">To be removed</f:facet>
</p:pickList>
<p:remoteCommand action="#{updateSiteObj.onDSTransfer}" name="ajaxSubmit3"/>
</p:column>
</p:dataTable>
UpdateSite.java
#ManagedBean(name = "updateSiteObj")
#SessionScoped
public class UpdateSite {
private List<DualListModel<String>> dsList = new ArrayList<DualListModel<String>>();
public List<DualListModel<String>> getDsList() {
return dsList;
}
public void setDsList(List<DualListModel<String>> dsList) {
this.dsList = dsList;
}
public String updateSiteDetails() {
ds.add(sg.getPrimaryDSID());
if (sg.getSecondaryDSID() != null) {
ds.add(sg.getSecondaryDSID());
}
System.out.print("DS:" + sg.getPrimaryDSID() + "=>" + sg.getSecondaryDSID());
DualListModel<String> tempDS = new DualListModel<String>();
tempDS.setSource(ds);
dsList.add(tempDS);
return "someSite?faces-redirect=true";
}
public void onDSTransfer() {
System.out.print("DSTransfer");
for (DualListModel<String> str1 : dsList) {
System.out.print("RemovedLBEntry:");
for (String dsName1 : str1.getTarget()) {
System.out.print("RemovedLB:" + dsName1);
}
}
}
}
When I try to call onDSTransfer after moving the values from source panel to target panel in picklist UI doesn't show any value from target.
Add update="#all" in p:remoteCommand.
You are doing a ajax call and not updating your UI.
<p:remoteCommand action="#{updateSiteObj.onDSTransfer}" name="ajaxSubmit3" update="#all"/>

JSF Dynamic Rendered Component's Value becomes null when the form is submitted

I have a JSF page which renders a text field depending on the value of a drop down using primefaces ajax listner. The dynamic rendering is done fine. but the problem is once I submit the form the the bound value of that textfield doesn't get bound instead it is shown as null.
this is the part of my JSF only the necessary fields are included here
<h:panelGroup id="textPanel" >
<h:form id="main" prependId="false">
<h:outputText value="WorkFlow ID:" />
<h:selectOneMenu id="workFlows" value="#{workFlowSelectionController.selectedWorkFlowId}" >
<p:ajax event="change" listener="#{workFlowSelectionController.dropDownChange}" update="textPanel"/>
<f:selectItems value="#{workFlowSelectionController.allActiveworkFlows}"/>
</h:selectOneMenu>
<p:inputText value="#{workFlowSelectionController.texField}" rendered="#{workFlowSelectionController.textfieldVisibility}"/>
<p:commandButton ajax="false" value="Next" action="#{workFlowSelectionController.addWorkFlowselectionDetails}"/>
</h:form>
</h:panelGroup>
this is my managed bean
#ManagedBean
#RequestScoped
public class WorkFlowSelectionController {
private boolean textfieldVisibility = false;
private String texField;
public void dropDownChange() {
logger.info("WorkFlowSelectionController.dropDownChange() entered");
if (selectedWorkFlowId != null) {
if (selectedWorkFlowId.equals("-1")) {
textfieldVisibility = true;
operationListStatus = false;
} else {
textfieldVisibility = false;
operationListStatus = true;
}
} else {
textfieldVisibility = false;
operationListStatus = true;
}
public void addWorkFlowselectionDetails() throws CloneNotSupportedException {
System.out.println("Selected Value of Text Field is" + texField);
}
public String getTexField() {
return texField;
}
public void setTexField(String texField) {
this.texField = texField;
}
}
i haven't included the dropdown code of the backing bean. i just need an idea of what i am doing wrong here if i remove the rendered attribute of the textfield it works fine.
thank you
Put the bean in the view scope instead of request scope. A request scoped is recreated on every single HTTP request. The boolean property will default to false again whenever you submit the form, so the submitted value won't be processed then.
#ManagedBean
#ViewScoped
public class WorkFlowSelectionController {
//
}
A view scoped bean will live as long as you're (ajax-) interacting with the same view by returning null or void from action(listener) methods.

select All checkbox in JSF without using Javascript

I am trying to select/unselect all checkboxes in the datatable using a single checkbox. As I am trying to set it on the server, I am unable to do so. I have looked around for solutions but could not get how to accomplish on the server side.
Here is the code.
xhtml file###
<rich:column styleClass="center-aligned-text">
<f:facet name="header">
<h:selectBooleanCheckbox id="selectAll" title="selectAll" valueChangeListener="#{workspace.selectAllComponents}">
<a4j:support event="onclick" reRender="listcomponents"/>
</h:selectBooleanCheckbox>
</f:facet>
<h:selectBooleanCheckbox id="selectComponent"
value="#{workspace.selectedComponentIds[componentInfo.id]}">
</h:selectBooleanCheckbox>
</rich:column>
Java File
// Select All and delete
public void selectAllComponents(ValueChangeEvent event){
// If the check all button is checked, set all the checkboxes as selected
if(!selectAll)
{
changeMap(selectedComponentIds,true);
setSelectAll(true);
}
else // If the button is unchecked, unselect all the checkboxes
{
changeMap(selectedComponentIds,false);
setSelectAll(false);
}
}
public void changeMap(Map<Long,Boolean> selectedComponentMap, Boolean blnValue){
if(selectedComponentMap != null){
Iterator<Long> itr = selectedComponentMap.keySet().iterator();
while(itr.hasNext()){
selectedComponentMap.put(itr.next(), blnValue);
}
setSelectedComponentIds(selectedComponentMap);
}
}
I am marking all the values in the list as true when the checkbox is checked and false when unchecked.
But the page doesn't reload the data properly.
Is my method to approach to the problem correct? Or is there a efficient alternative?
It's because the ValueChangeEvent occurs before the update model phase, so the value you change gets overwritten.
Do this in the public void selectAllComponents(ValueChangeEvent event)
if (event.getPhase() != PhaseId.INVOKE_APPLICATION) {
event.setPhase(PhaseId.INVOKE_APPLICATON);
event.queue();
} else {
//do your stuff here
}
Or just before your code add next line code in your original method
selectAll = (Boolean) event.getNewValue();

Resources