I’m still new to CUBA Studio, and have a need to figure out how to update an uneditable ‘position’ field from the most recent (based off of entered date) position created in a composition.
First, the setup:
Employee entity with firstName, lastName, position (uneditable), payHistory Composition
EmployeePayHistory entity with position, payRate, payStartDate
So, when you create a new Employee entry, the ‘position’ field will be automatically updated with the ‘position’ field entry from the EmployeePayHistory entry with the most recent ‘payStartDate’
This is obviously very much a ‘help me learn’ request. I’ve messed around with the EmployeeBrowse java controller, trying to figure out what to inject and what event to subscribe to, but I’m basically shooting in the dark. A specific example of how to accomplish this would go a great distance to helping me figure out how to solve these things myself in the future.
Thanks in advance for any guidance you can provide!
As I understand each employee has a collection of EmployeePayHistory items. The type of relation between Employee and EmployeePayHistory is composition.
So, when you create a new Employee entry, the ‘position’ field will be automatically updated with the ‘position’ field entry from the EmployeePayHistory entry with the most recent ‘payStartDate’
The fact that a collection of pay history items is a composition means that pay history items may be created only for existing employee. At the moment the employee is created, there is no pay history yet.
Please clarify in more details what and when should happen.
I apologize for the lack of clarity. Yes, the Employee edit screen contains:
First Name
Last Name
Position (Uneditable, Not Mandatory)
Employee Pay History Composition table
When the Employee Pay History table is altered in any way (Create, Edit, Delete) the Employee Pay History entry with the most recent Employee Start Date will save its own ‘Position’ entry to the Employee ‘Position’ field.
The goal is to keep the ‘Position’ properly grouped with the Pay History entity, but also have it viewable in the Employee entity.
If you want to handle this in screen controller, then your controller may look like this:
@UiController("sample_Employee.edit")
@UiDescriptor("employee-edit.xml")
@EditedEntityContainer("employeeDc")
@LoadDataBeforeShow
public class EmployeeEdit extends StandardEditor<Employee> {
/**
* Handles the case when new PayHistory is added or removed
*/
@Subscribe(id = "payHistoriesDc", target = Target.DATA_CONTAINER)
public void onPayHistoriesDcCollectionChange(CollectionContainer.CollectionChangeEvent<PayHistory> event) {
if (event.getChangeType() == CollectionChangeType.ADD_ITEMS ||
event.getChangeType() == CollectionChangeType.REMOVE_ITEMS) {
String latestPosition = evaluateLatestPosition();
getEditedEntity().setPosition(latestPosition);
}
}
/**
* Handles the case when existing PayHistory is modified
*/
@Subscribe(id = "payHistoriesDc", target = Target.DATA_CONTAINER)
public void onPayHistoriesDcItemPropertyChange(InstanceContainer.ItemPropertyChangeEvent<PayHistory> event) {
String latestPosition = evaluateLatestPosition();
getEditedEntity().setPosition(latestPosition);
}
@Nullable
private String evaluateLatestPosition() {
List<PayHistory> payHistories = getEditedEntity().getPayHistories();
if (payHistories != null) {
return payHistories.stream()
.max(Comparator.comparing(PayHistory::getStartDate))
.map(PayHistory::getPosition)
.orElse(null);
}
return null;
}
}
You can read about collection containers here and about handling events in Studio here
An alternative way to go is to implement this behavior not in the screen controller, but using EntityChangedEvent or EntityListener. In this case, the position of the employee will be updated when you change pay items from any part of your application, not only from the screen controller.