Ok, this is a weird one.
In XPages my dataSource is a Java Object. A Managed bean or PageController. I\'m using bootstrap via the Ext. Library.
What I\'d
Any UIComponent has a setValid(boolean)
method. All controls also have a binding
property, which can be used to bind that component to a Java object, e.g. a property in your bean.
However, if your custom control is used multiple times, you can't use that, because all instances would be trying to bind to the same bean property.
But, with a bit of cunning thought, it's possible to take advantage of the same concept. If your bean has a Map<String, Component> myCunningBindings
, you could add a collection of bindings dynamically using this code in the loaded property:
<this.loaded><![CDATA[${javascript:myBean.getMyCunningBindings().put(compositeData.fieldMapping, this);
return "";}]]>
</xp:this.loaded>
So the first line of the code gets the map and adds an element. That element has a value (the component itself) and a label. For the label, we get the field mapping that you're also likely to be passing in via compositeData
. Finally, we return true.
Your bean that does the validation should know where it's saving it to, so you should be able to calculate the field mapping that was passed into compositeData, which will be the key you need to look for in the Map. And from there, you have the component to call setValid(false) on.
What I do is using a custom validator for the component. For instance,
<xp:this.validators>
<xp:customValidator validate="#{javascript:controller.validateDuration(this)}"></xp:customValidator>
</xp:this.validators>
In my controller class:
public void validateDuration(UIComponent source) {
// Do my checks...
// If fails,
BeanUtils.setControlInvalid(source, "Format Error at date time!");
}
BeanUtils methods to invalidate a specific component and generate a validation error message:
public static void setControlInvalid(UIComponent editableComponent, String message) {
if(StringUtil.isEmpty(message) || editableComponent==null) return;
if(editableComponent instanceof EditableValueHolder) {
((EditableValueHolder) editableComponent).setValid(false);
postFacesMessage(editableComponent, FacesMessage.SEVERITY_ERROR, message);
}
}
public static void postFacesMessage(UIComponent component, Severity severity, String msg) {
if(StringUtil.isEmpty(msg) || component==null) return;
FacesContext fc=FacesContext.getCurrentInstance();
FacesMessage message=new FacesMessage(severity, msg, msg);
fc.addMessage(component.getClientId(fc), message);
}