Reputation: 1501
I am using primefaces data table to display a list of data. I want my users to be able to select multiple rows after which an operation will be executed on the data represented by the selected rows. Everything works well up untill the operation is executed where i discover that the selection could not be resolved.
Below is my xhtml page
<h:form enctype="multipart/form-data" id="upload">
<primefaces-p:panel closable="false" collapsed="false" header="Excel Contact Uploader" id="pnlupload" rendered="true" toggleable="false" visible="true" widgetVar="pnlupload">
<primefaces-p:growl id="msg" showDetail="true" life="3000" showSummary="true">
</primefaces-p:growl>
<primefaces-p:fileUpload auto="true"
allowTypes="/(\.|\/)(xls)$/"
sizeLimit="1024000"
mode="advanced"
multiple="true" invalidFileMessage="Invalid file type" invalidSizeMessage="File too large" dragDropSupport="true" fileUploadListener="#{excelFileController.handleFileUpload}" showButtons="true" update="msg, tblcontacts
" required="false"/>
<br />
<br />
<primefaces-p:scrollPanel rendered="true" style="height:200px;">
<primefaces-p:dataTable emptyMessage="No Contacts Uploaded" id="tblcontacts" rendered="true" rows="8"
value="#{excelFileController.contacts}" var="contact" style="width:50pc;">
<primefaces-p:column style="width:18px" headerText="Select">
<h:selectBooleanCheckbox value="#{contact.selected}" />
</primefaces-p:column>
<primefaces-p:column headerText="File Name">
#{contact.groupName}
</primefaces-p:column>
<primefaces-p:column headerText="Number of Contacts">
#{contact.numberofentries}
</primefaces-p:column>
<primefaces-p:column>
<h:button outcome="blkedit?faces-redirect=true" rendered="true" value="Edit">
<f:param name="contact" value="#{contact.contactId}"/>
</h:button>
</primefaces-p:column>
</primefaces-p:dataTable>
</primefaces-p:scrollPanel>
<br />
</primefaces-p:panel>
<h:commandButton value="Delete" id="btndelete" action="#{excelFileController.removeContact}" immediate="true" disabled="false" rendered="true"/>
<h:message for="btndelete" />
</h:form>
and Below is my backing bean
@Named
@ViewAccessScoped
public class ExcelFileController implements Serializable, IFileController {
/**
*
*/
private static final long serialVersionUID = -8117258104485487921L;
@Inject
PhoneNumberFormatter formatter;
@Inject
@Authenticated
UserProfile profile;
public PhoneNumberFormatter getFormatter() {
return formatter;
}
public void setFormatter(PhoneNumberFormatter formatter) {
this.formatter = formatter;
}
@EJB
BulkContactDeleter deleter;
@Inject
Logger logger;
@Inject
@CurrentContext
FacesContext context;
@Inject
BulkSMSContactListProducer listProducer;
@Inject
ConfigurationListProducer producer;
private BulkSMSContacts[] contactsSelected;
private List<BulkSMSContacts> contacts;
public BulkSMSContacts[] getContactsSelected() {
return contactsSelected;
}
public void setContactsSelected(BulkSMSContacts[] contactsSelected) {
this.contactsSelected = contactsSelected;
}
/*
* public BulkContactDataModel getContactDataModel() { return
* contactDataModel; }
*/
@PostConstruct
public void init() {
logger.log(Level.INFO, "Entering excel file controller");
/*
* contactDataModel = new BulkContactDataModel(
* listProducer.getBulkSMSContacts());
*/
this.contacts = listProducer.getBulkSMSContacts();
}
@Override
public String removeContact() {
int contactsdeleted = 0;
if (this.contacts != null) {
/*
* for (BulkSMSContacts contacts : contactsSelected) { if (contacts
* != null) { deleter.deleteContact(contacts); contactsdeleted += 1;
* }
*/
for (BulkSMSContacts c : contacts) {
if (c.isSelected()) {
deleter.deleteContact(c);
contactsdeleted += 1;
}
}
contacts = listProducer.getBulkSMSContacts();
logger.log(Level.INFO, "Deleted " + contactsdeleted + " Contacts");
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "Success", contactsdeleted
+ " entries where deleted successfully"));
} else {
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error",
"No contact file was selected!"));
}
return null;
}
public List<BulkSMSContacts> getContacts() {
return contacts;
}
public void setContacts(List<BulkSMSContacts> contacts) {
this.contacts = contacts;
}
}
Below is my model definition
@Entity
public class BulkSMSContacts implements Serializable {
private static final long serialVersionUID = -6444763251149211384L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@XmlAttribute
private long contactId;
@XmlElement
@NotNull(message = "message.validator.notnull")
@Size(min = 9, max = Integer.MAX_VALUE, message = "message.validator.size")
@Column(nullable = false, length = Integer.MAX_VALUE, unique = false)
@Basic(fetch = FetchType.EAGER)
private String contacts;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "Id", nullable = false)
@XmlElement(type = SMSAccount.class)
private SMSAccount account;
@NotNull(message = "message.validator.notnull")
@Size(min = 2, max = 100, message = "message.validator.size")
@Column(length = 100, nullable = false, unique = false)
@XmlElement
private String groupName;
@Column(nullable = true)
private int numberofentries = 0;
@javax.persistence.Transient
private boolean selected;
//getters and setters
The problem is that when the delete button is clicked(albeit when the removeContact() method is called. All the rows evaluate to none being selected.
I have also tried using the primefaces showcase approach but still the sample problem.
Please am I doing something wrong??
Upvotes: 0
Views: 6238
Reputation:
I don't see why you set a selection attribute within an entity class. Try to do it this way
set a data Model :
public class BulkSMSContactsDataModel extends ListDataModel<BulkSMSContacts> implements SelectableDataModel<BulkSMSContacts> {
public BulkSMSContactsDataModel() {
}
public BulkSMSContactsDataModel(List<BulkSMSContacts> data) {
super(data);
}
@Override
public BulkSMSContacts getRowData(String rowKey) {
List<BulkSMSContacts> contacts = (List<BulkSMSContacts>) new yourDao.getListOfBulkSMSContacts(); //yourDAO :BulkSMSContactsSelector i guess
for(BulkSMSContacts c : contacts) {
if(String.valueOf(c.getContactId()).equals(rowKey))
return c;
}
return null;
}
@Override
public Object getRowKey(BulkSMSContacts obj) {
return String.valueOf(obj.getContactId());
}
}
configure your bean :
public class ExcelFileController implements Serializable, IFileController {
private BulkSMSContacts[] contactsSelected;
private List<BulkSMSContacts> contacts;
private BulkSMSContacts[] selectedcontacts;
private BulkSMSContactsDataModel contactsList;
public ExcelFileController() {
contactsList = new BulkSMSContactsDataModel(contacts);
}
// getters and setters
// the rest of your code
}
configure your xhtml
<p:dataTable emptyMessage="No Contacts Uploaded" id="tblcontacts" rendered="true" rows="8" value="#{excelFileController.contactsList}" var="contact" style="width:50pc;" selection="#{excelFileController.selectedcontacts}">
<p:column selectionMode="multiple" style="width:20px" />
<p:column headerText="File Name">
#{contact.groupName}
</p:column>
<p:column headerText="Number of Contacts">
#{contact.numberofentries}
</p:column>
<!-- the rest -->
Update your UI.
use p instead of primefaces-p it will make it easier to read your Code. :)
Upvotes: 2
Reputation: 85779
In order to know the selected contacts
, the dataTable and the UI Command component i.e. <h:commandButton>
, <p:commandButton>
, etc., must be in the same form. This means, your contacts datatable and your delete button must be inside the same <h:form>
<h:form>
<!-- based in your code (pretty odd by the way)... -->
<primefaces-p:dataTable emptyMessage="No Contacts Uploaded" id="tblcontacts"
rendered="true" rows="8" value="#{excelFileController.contacts}"
var="contact" style="width:50pc;">
<!-- your columns... -->
</primefaces-p:dataTable>
<primefaces-p:commandButton value="Delete contacts"
action="#{excelFileController.removeContact}" />
</h:form>
Also, check that you don't have nested forms in your page.
More info:
The problem seems to be in the CDI annotations. In order to make your ExcelFileController
being alive is to initialize the conversation somewhere (that isn't showed anywhere in your code). Another solution would be using the JSF annotations instead:
//@Named
//@ViewAccessScoped
@ManagedBean
@ViewScoped
public class ExcelFileController implements Serializable, IFileController {
//rest of your code...
}
Upvotes: 1