javascriptjquerybootstrap-datetimepicker

Reduce logical pattern repetition for minDate and maxDate from Bootstrap DateTimePicker


The following logical pattern repeats several times:

$("#dt_start").on("dp.change", function (e) {
    $('#dt_end').data("DateTimePicker").minDate(e.date);
});

$("#dt_end").on("dp.change", function (e) {
    $('#dt_start').data("DateTimePicker").maxDate(e.date);
});

After identifying this pattern, I tried mapping as follows:

const pairsOfDates = [
    {
        start: 'dt_start',
        end: 'dt_end'
    },
    {
        start: 'dt_start_edit',
        end: 'dt_end_edit'
    }
    // among others...
]

Therefore, it would have a forEach to iterate over each position and mount the jQuery listeners:

pairsOfDates.forEach(function (config) {
    
    // Listener for start date
    $('#' + config.start).on("dp.change", function (e) {
        updatesDeadlines(e, config.start, config.end, false);
    });

    // Listenor for end date
    $('#' + config.end).on("dp.change", function (e) {
        updatesDeadlines(e, config.start, config.end, true);
    });
});

And finally the updatesDeadlines function:

function updatesDeadlines(e, idStart, idEnd, isMaxDate) {
    if (!e.date) return;
    
    if (isMaxDate) {
        $('#' + idStart).data("DateTimePicker").maxDate(e.date);
    } else {
        $('#' + idEnd).data("DateTimePicker").minDate(e.date);
    }
}

This worked as I expected, but I continue to believe that using this mapping may not be the most efficient or appropriate way, or may even make it difficult to maintain in the future.

So how could I reduce the repetition of this pattern? Or is using mapping the most recommended? Or just keep it as it currently is?


Solution

  • After discussing the DRY principle and separation of concerns in the comments, I confirmed that the array mapping pattern I initially explored is indeed the most appropriate solution for this context.

    It effectively isolates the specific element selectors (the "magic strings") from the event logic, making the code easier to maintain.

    Here is the final implementation:

    const pairsOfDates = [
        {
            start: 'dt_start',
            end: 'dt_end'
        },
        {
            start: 'dt_start_edit',
            end: 'dt_end_edit'
        }
    ]
    
    pairsOfDates.forEach(function (config) {
        $('#' + config.start).on("dp.change", function (e) {
            updatesDeadlines(e, config.start, config.end, false);
        });
    
        $('#' + config.end).on("dp.change", function (e) {
            updatesDeadlines(e, config.start, config.end, true);
        });
    });
    
    function updatesDeadlines(e, idStart, idEnd, isMaxDate) {
        if (!e.date) return;
        
        if (isMaxDate) {
            $('#' + idStart).data("DateTimePicker").maxDate(e.date);
        } else {
            $('#' + idEnd).data("DateTimePicker").minDate(e.date);
        }
    }
    

    This approach allows me to easily add new date pairs in the future simply by adding a new object to the pairsOfDates array, keeping the codebase clean and maintainable.