I have a question about the architecture and event lifecycle of lightning components: how can I validate more than one depending attributes?
Think about the following example: I have a DateRangePicker component containing a startDate and endDate property. Obviously the startDate should reference a Date which is earlier in time as the endDate. I tried the following:
DateRangePicker.cmp:
<aura:component>
<!-- attributes -->
<aura:attribute name="startDate" type="Date" />
<aura:attribute name="endDate" type="Date" />
<!-- event handler -->
<aura:handler name="change" value="{!v.startDate}" action="{!c.onDateChange}" />
<aura:handler name="change" value="{!v.endDate}" action="{!c.onDateChange}" />
</aura:component>
Whenever either the startDate or endDate properties are changing (through user input, server validation, whatever action appears) I am going to validate that startDate is before endDate:
DateRangePickerController.js:
({
onDateChange: function(component, event, helper) {
var startDate = component.get("v.startDate");
var endDate = component.get("v.endDate");
//validate startDate is before endDate, otherwise change order
if($A.localizationService.isBefore(endDate, startDate))
{
//changing the order of the two properties
component.set("v.startDate", endDate);
component.set("v.endDate", startDate);
}
)}
The problem about this small example is that setting the new values is triggering a change event immediately for each set-operation and calling the same function again.
Another problem is that when you set the dates programmatically like (pseudo code):
init:function() {
component.set("v.startDate", new Date());
component.set("v.endDate", getTomorrow(new Date()));
}
the value change event is also triggered immediately for the startDate (before the endDate has been set) and again for endDate – so it is hard to determine in the function call if there is another change or not.
I am missing (or not found) a concept about collecting all property changes to validate them at once in a later point in the lifecycle like invalidating/flagging properties and validate them all at a single point. And resolve the conflict about storing the current value to make accessible from the outside and also be able to react on change events when the value did change from outside.
Or could I achieve a similar behavior by using a different technique (private attributes, setter methods, what ever concept is useful)?
Any ideas about architecture are highly appreciated.
Thanks
Chris
Best Answer
So far I found out a good way is the usage of <aura:method> (https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_tag_method.htm?search_text=aura:method
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cmp_methods.htm?search_text=aura:method)
Rather bind directly on both change events individual I wrote one method which accepts two parameters for both values:
where inside my controller I do the validation logic like
and storing the values in private like attribute way:
So no more change handler on the attributes.
The downside is that I can only call the method from JavaScript and not directly set values through expressions in the component markup.
Hope that helps Chris