“I’m working on a JavaFX application with a TableView for managing employee records. I have an EmployeeRepository class for handling CRUD operations that communicates with “CsvHandler” class to save the data in a csv and an EmployeeManagementController for interacting with the TableView.
The issue I’m facing is that when I add or update an employee record through the dialog launched by EmployeeDetailsController, the TableView in EmployeeManagementController does not update to reflect these changes.
Here’s a brief overview of the relevant code:
-
EmployeeRepository: Manages CRUD operations and maintains an ObservableList<Employee> that the TableView should be bound to.
-
EmployeeManagementController: Initializes the TableView with employeeObservableList, which is supposed to be updated when records are added or updated.
-
EmployeeDetailsController: Handles the dialog for adding or updating records and calls methods in EmployeeRepository to save the data.
Despite updating the ObservableList in EmployeeRepository after operations, the TableView in EmployeeManagementController does not reflect these changes.
Here’s the EmployeeRepository Class:
public class EmployeeRepository {
private final CsvHandler csvHandler;
private final String EMPLOYEE_DATA_FILE = "Data/employeeData.csv";
private final List<String[]> employeeData;
private final ObservableList<Employee> employeeList;
private final String[] HEADERS;
public EmployeeRepository() {
csvHandler = new CsvHandler(EMPLOYEE_DATA_FILE);
employeeData = csvHandler.retrieveCsvData(true);
employeeList = FXCollections.observableArrayList(getAllEmployees());
HEADERS = csvHandler.retrieveFieldNames();
}
public Employee convertArrayToEmployee(String[] employeeData) {
return new Employee(
Integer.parseInt(employeeData[0]),
employeeData[1],
employeeData[2],
employeeData[3],
employeeData[4],
employeeData[5],
employeeData[6],
employeeData[7],
employeeData[8],
employeeData[9],
employeeData[10],
employeeData[11],
employeeData[12],
employeeData[13],
employeeData[14],
Double.parseDouble(employeeData[15]),
Double.parseDouble(employeeData[16]),
Double.parseDouble(employeeData[17]),
Double.parseDouble(employeeData[18]),
Double.parseDouble(employeeData[19]),
Double.parseDouble(employeeData[20])
);
}
public List<Employee> getAllEmployees() {
List<Employee> employees = new ArrayList<>();
for (String[] row : employeeData) {
employees.add(convertArrayToEmployee(row));
}
return employees;
}
public ObservableList<Employee> getEmployeeList() {
return employeeList;
}
public boolean recordExists(String[] record, int currentEmpId) {
for (String[] row : employeeData) {
if (Integer.parseInt(row[0]) != currentEmpId && // EmployeeID
(record[4].equals(row[4]) || // address
record[5].equals(row[5]) || // phone number
record[7].equals(row[7]) || // SSS
record[8].equals(row[8]) || // PhilHealth
record[9].equals(row[9]) || // TIN
record[10].equals(row[10]))) { // Pag-IBIG
return true;
}
}
return false;
}
public void addEmployeeRecord(String[] record) {
if (recordExists(record, -1)) {
AlertUtil.showDuplicateRecordExists();
return;
}
employeeData.add(record);
employeeList.add(convertArrayToEmployee(record));
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordSavedAlert();
System.out.println("Record saved");
}
public int getNewEmployeeID() {
return Integer.parseInt(employeeData.getLast()[0]) + 1;
}
public void updateEmployeeRecord(String[] record) {
if (recordExists(record, Integer.parseInt(record[0]))) {
AlertUtil.showDuplicateRecordExists();
return;
}
for (int i = 0; i < employeeData.size(); i++) {
String[] row = employeeData.get(i);
if (row[0].equals(record[0])) {
employeeData.set(i, record);
employeeList.set(i, convertArrayToEmployee(record));
break;
}
}
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordUpdatedAlert();
System.out.println("Record Updated");
}
public void deleteEmployeeRecord(int employeeId) {
employeeData.removeIf(row -> row[0].equals(String.valueOf(employeeId)));
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordDeletedAlert();
System.out.println("Record deleted");
}
}
Here’s the EmployeeManagementController:
public class EmployeeManagementController {
private final EmployeeRepository empDataService;
private final ObservableList<Employee> employeeObservableList;
@FXML
private TableView<Employee> employeeTable;
@FXML
private TableColumn<Employee, Integer> employeeIdColumn;
@FXML
private TableColumn<Employee, String> firstNameColumn, lastNameColumn, tinNoColumn, sssNoColumn, philhealthNoColumn, pagibigNoColumn;
public EmployeeManagementController() {
empDataService = new EmployeeRepository();
employeeObservableList = empDataService.getEmployeeList();
}
@FXML
public void initialize() {
initializeTableColumns();
loadEmployeeData();
handleViewEmployeeDetails();
}
@FXML
private void handleAddNewRecord() {
new EmployeeDetailsController().displayEmployeeDialog(false, null, false);
}
@FXML
private void handleUpdateRecord() { Employee selectedEmployee = selectedEmployee();
if (selectedEmployee != null) {
new EmployeeDetailsController().displayEmployeeDialog(true, selectedEmployee, false);
} else {
AlertUtil.showNoSelectionAlert("Please select an employee record to update");
}
}
@FXML
public void handleDeleteRecord() {
Employee selectedEmployee = selectedEmployee();
if (selectedEmployee == null) {
AlertUtil.showNoSelectionAlert("Please select an employee record to delete");
return;
}
boolean confirmed = AlertUtil.showConfirmationAlert("Confirm Deletion", "Are you sure you want to delete this employee record? This action cannot be undone.");
if (confirmed) {
empDataService.deleteEmployeeRecord(selectedEmployee.getEmployeeID());
}
}
private void handleViewEmployeeDetails() {
employeeTable.setOnMouseClicked((MouseEvent event) -> {
if (event.getClickCount() == 2) {
new EmployeeDetailsController().displayEmployeeDialog(false, selectedEmployee(), true);
}
});
}
private void initializeTableColumns() {
employeeIdColumn.setCellValueFactory(new PropertyValueFactory<>("employeeID"));
firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
tinNoColumn.setCellValueFactory(new PropertyValueFactory<>("tinNumber"));
sssNoColumn.setCellValueFactory(new PropertyValueFactory<>("sssNumber"));
philhealthNoColumn.setCellValueFactory(new PropertyValueFactory<>("philhealthNumber"));
pagibigNoColumn.setCellValueFactory(new PropertyValueFactory<>("pagibigNumber"));
bindTableColumnsToTableViewWidth();
}
private void loadEmployeeData() {
employeeTable.setItems(employeeObservableList);
}
private Employee selectedEmployee() {
return employeeTable.getSelectionModel().getSelectedItem();
}
}
Here’s the EmployeeDetailsController:
public class EmployeeDetailsController {
private final EmployeeRepository empRepository = new EmployeeRepository();
private Employee employee;
private boolean updateMode = false;
public void setEmployee(Employee employee) {
this.employee = employee;
updateMode = true;
populateFields();
}
@FXML
public void handleSaveRecord() {
if (!validateFields()) {
AlertUtil.showIncompleteDataAlert();
return;
}
try {
if (AlertUtil.confirmDetails()) {
String[] record = retrieveInputAsStringArray();
if (updateMode) {
handleUpdateMode(record);
} else {
handleAddMode(record);
}
}
} catch (NumberFormatException e) {
AlertUtil.showAlert(Alert.AlertType.ERROR, "Invalid Number Format", "Please enter a valid number.");
}
}
private void handleAddMode(String[] record) {
empRepository.addEmployeeRecord(record);
}
private void handleUpdateMode(String[] record) {
empRepository.updateEmployeeRecord(record);
}
public void displayEmployeeDialog(boolean updateMode, Employee employee, boolean showOnly) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/EmployeeDetails.fxml"));
DialogPane empDetailsDialogPane = loader.load();
EmployeeDetailsController controller = loader.getController();
if (updateMode) {
controller.setEmployee(employee);
} else if (employee != null) {
controller.setEmployee(employee);
controller.disableTextFields();
}
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(empDetailsDialogPane);
if (showOnly) {
empDetailsDialogPane.lookupButton(ButtonType.OK).setVisible(false);
empDetailsDialogPane.lookupButton(ButtonType.CANCEL).setVisible(false);
}
Optional<ButtonType> clickedButton = dialog.showAndWait();
if (clickedButton.isPresent() && clickedButton.get() == ButtonType.OK && !showOnly) {
controller.handleSaveRecord();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void disableTextFields() {
for (TextField textField : textFields) {
textField.setEditable(false);
}
}
}
Ibrahim Harby is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.