In this, the user inserted the fields in tab-order. After leaving the field salary (doing a auto submit, triggering the job field), the job validator executes and marks a red border to inform the user of the issue. As the user has never inserted the field up to this point, this is not very nice. One valid change is to remove the mandatory flag from the attribute and delegate the validation towards entity level. But then, you will lose the "red border at attribute" response and get a FacesMessage leaving the user in question, which attribute to change to solve the invalid entity.
Andrejus Baranovskis has written a nice article, how to solve this issue when encountering attributes on the same entity, the validation is occuring on:
http://andrejusb.blogspot.de/2017/02/setting-invalid-fields-for-ui-in-adf-bc.html
So let us extend the usecase a bit.
Issue:
For many List of Value components, users do not want to see the key (for example JobId) in the input text, but the looked up value (JobTitle in this case).
To implement this, there are many options to take. To combine the lov requirement and the delayed attribute validation, let me show you one implementation, that works and is quite declarative.
Define the following use cases:
- Users want to be able to change the Job of an employee using a list of values showing the title, not the id of the job
- When changing the salary of an employee, the job will be nullified
- An empty job leads to a validation, but this should only occur on save button or navigation
The second use case defines the usage of partial triggers / auto submit on JSF side later on.
Solution:
To start, we need the base Entity (Employees), a View Object on that entitity (EmployeesView) and a Lookup View Object (JobsLookupView).
Next create a Transient Attribute on Employees Entity, representing the JobName. This will be the target Attribute for the delayed validation and is the base attribute for the lov.
This Attribute uses an expression referring a ViewAccessor on JobsLookupView:
Expression:
JobId != null ? JobsLookupView.getAllRowsInRange().find{it['jobId']==JobId}['jobTitle'] : null
Next, we will add the entity validation (referring Andrejus' blog entry):
(opt. add failure message)
Add dependencies on Entity attributes:
Additionally remove the mandatory flag from the JobId Attribute (to allow entity validation to do the not null check)
Add LOV to EmployeesView JobName Attribute:
(rem: We can use the Employee-level view accessor in this case because we do not use dynamic query components in this example, so no additional view object instances needed).
Create UI
Finally just create a simple Form Layout on a page, removing the JobId Attribute and ensuring the InputListOfValues Component for JobName.
Then update the following attributes for Salary resp. JobName Components:
Additionally, drag the CreateInsert Operation onto the page, to create a new record.
When running the app, and creating a new employee again tabbing through the form, we will see, there is no validation when tabbing out of the salary field (because the showRequired=true instead of mandatory=true).
When commit or navigation is triggered, the entity validation will fire, but because of the special validation attribute, we will see this on the single attribute instead of a FacesMessage.
This is especially helpful, if you are editing data inside a popup.
TL;DR / Result:
Please feel free to checkout a demo application implementing the shown at the german ADFCommunity github repository
https://github.com/ADFCommunityDE/DelayedAttributeValidationOnLookup.git
Any questions regarding this topic or want to see a feature/idea implemented in ADF? Just send me a message ;)
mail: mke@team-pb.de
twitter: @MarkusKlenke
Cheers!
Keine Kommentare:
Kommentar veröffentlichen