Search code examples
validationdatetimeaureliacustom-element

Aurelia validate one datetime is greater than the other


I have two date/times that come from a db, however these are split into four (two dates and two times) on the view, both the date and time are custom elements. See below.

enter image description here

My issue is my start date/time cannot be greater than my end date/time. I know how to do this in c#:

  • Check whether date string contains a default time 00:00:00, if so remove.
  • Parse date/time strings in a new datetime
  • Repeat for second date/time
  • Validate whether from < to (return from < to)

But I don't know how to do this in Aurelia without doing a API call. I have noted isLessThan, however I would need to parse my strings into a datetime before I can do that.

      bind(){
            return this.dataContext.getContent(this.id)
                .then(baseContent => {
                    this.baseContent = baseContent;
                     this.validator = this.validation.on(this)                                         
    .ensure('baseContent.ValidFromDate').isNotEmpty()
                            .ensure('baseContent.ValidFromTime').isNotEmpty()
                            .ensure('baseContent.ValidToDate').isNotEmpty()
                            .ensure('baseContent.ValidToTime').isNotEmpty()
.ensure('baseContent.ValidFromDate / baseContent.ValidFromTime').isLessThan('baseContent.ValidToDate / baseContent.ValidToTime')
;
                }); }

I know the above doesn't work, I am new to Aurelia and still finding my feet with it.

UPDATE

I've tried the following but received a:

Unhandled promise rejection TypeError: path.split is not a function

I think the issue is it doesn't know what to assign the error message to but I could be wrong.

.ensure(this.datetimeformat.format(baseContent.ValidFromDate, baseContent.ValidFromTime)).isLessThan(this.datetimeformat.format(baseContent.ValidToDate, baseContent.ValidFromTime));

import moment from 'moment';

export class DateTimeFormat {
    format(date, time) {

        if (date.indexOf("T") > -1) {
            date = date.split('T')[0];
        }

        return moment(date + 'T' + time, 'DD/MM/YYYY HH:mm:ss');
    }
}

I noticed one of the answers used a computedFrom however as I need to first change these into DateTime, and parse back I don't know what I am meant to provide where.

UPDATE

.ensure('baseContent.ValidFromDate', (config) => { config.computedFrom(['baseContent.ValidFromDate', 'baseContent.ValidFromTime', 'baseContent.ValidToDate', 'baseContent.ValidToTime']) }).isNotEmpty().passes(() => {
                        return this.datetimeformat.format(this.baseContent.ValidFromDate, this.baseContent.ValidFromTime) < this.datetimeformat.format(this.baseContent.ValidToDate, this.baseContent.ValidToTime);
                    })

I think I am getting closer, but still not working :-(

I have also tried

.ensure('baseContent.ValidFromDate', (config) => { config.computedFrom(['baseContent.ValidFromDate', 'baseContent.ValidFromTime', 'baseContent.ValidToDate', 'baseContent.ValidToTime']) }).if(() => {
                        return this.baseContent.ValidFromDate !== null && this.baseContent.ValidFromTime !== null && this.baseContent.ValidToDate !== null && this.baseContent.ValidToTime !== null})
                        .passes( () => {return this.datetimeformat.format(this.baseContent.ValidFromDate, this.baseContent.ValidFromTime) < this.datetimeformat.format(this.baseContent.ValidToDate, this.baseContent.ValidToTime)})
                    .endIf().isNotEmpty()

No errors with developer tools.

function validateFromDateTimeIsBeforeToDateTime(dateFrom, timeFrom, dateTo, timeTo) {
        debugger;
        if (dateFrom !== null && dateFrom !== undefined &&
        timeFrom !== null && timeFrom !== undefined &&
        dateTo !== null && dateTo !== undefined &&
        timeTo !== null && timeTo !== undefined) {

            return this.datetimeformat.format(dateFrom, timeFrom) < this.datetimeformat.format(dateTo, timeTo);
    } 
    else {
        return true;
    }
}

                    .ensure('baseContent.ValidFromDate').isNotEmpty().passes(validateFromDateTimeIsBeforeToDateTime(this.baseContent.ValidFromDate, this.baseContent.ValidFromTime, this.baseContent.ValidFromDate, this.baseContent.ValidFromTime))
                    .ensure('baseContent.ValidFromTime').isNotEmpty()
                    .ensure('baseContent.ValidToDate').isNotEmpty().passes(validateFromDateTimeIsBeforeToDateTime(this.baseContent.ValidFromDate, this.baseContent.ValidFromTime, this.baseContent.ValidFromDate, this.baseContent.ValidFromTime))
                    .ensure('baseContent.ValidToTime').isNotEmpty()

This however throws an "Unhandled promise rejection TypeError: Unable to get property 'datetimeformat' of undefined or null reference"


Solution

  • After a-lot of investigation, fixing bugs here and there, I noted the outstanding issue was from my formatting class, it wasn't creating the date/time (using moment.js) correctly (after the user has selected from the calendar), meaning it returned 'invalid date' which you cannot compare on :-|

    This will work:

    this.validator = this.validation.on(this)
                        .ensure('baseContent.ValidFromDate', (config) => { config.computedFrom(['baseContent.ValidFromDate', 'baseContent.ValidFromTime', 'baseContent.ValidToDate', 'baseContent.ValidToTime']) })
                            .if(() => {
                                return this.baseContent.ValidFromDate !== null && this.baseContent.ValidFromTime !== null && this.baseContent.ValidToDate !== null && this.baseContent.ValidToTime !== null })
                                .passes( () => { return this.datetimeformat.format(this.baseContent.ValidFromDate, this.baseContent.ValidFromTime) < this.datetimeformat.format(this.baseContent.ValidToDate, this.baseContent.ValidToTime) })
                                .withMessage('< Valid To')
                            .endIf()