I use Bootstrap 4 as the framework for most sites that I build and I’m mostly happy with how it works, though one area where I think it could be a bit more user friendly is in Form Validation. This works fine for basic validation tasks but doesn’t make it easy to add in you’re own custom validation rules.

Possibly this deficiency is because they don’t see any point in reinventing the wheel given that there are already good libraries out there for validating forms such as jQuery Validation.

In my case I wanted to validate an order date and only allow the form to be submitted if it was more than 30 days in the past. While this could be accomplished using the max property of a datetime input I wanted to use a text input with the date chosen using the Date Range Picker plugin to ensure it worked consistently across all browsers and to give me more control of the picker.

In order to get this working I needed to create a custom rule to validate the date format as well as one to check it was at least 30 days in the past and to then apply them to my order date field.

Index.cshtml – HTML

The form inputs are generated for my orderOnline object using the ASP.NET Core Razor Tag Helpers. The OrderDate field is specified as text and autocomplete is disabled.

<div id="divOnline" class="d-none">
    <div class="row">
        <div class="col offset-lg-2 offset-xl-3 col-lg-8 col-xl-6">
            <form asp-controller="Home" asp-action="OrderOnline" id="OrderOnlineForm" method="post" role="form" class="needs-validation" novalidate>
                <div class="form-group row">
                    <div class="col-sm-5 col-md-4 col-xl-3">
                        <label asp-for="@orderOnline.EmailAddress">
                        </label>
                    </div>
                    <div class="col-sm-7 col-md-8 col-xl-9">
                        <input asp-for="@orderOnline.EmailAddress" class="form-control form-control-sm" type="email" required />
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-sm-5 col-md-4 col-xl-3">
                        <label asp-for="@orderOnline.OrderDate">
                        </label>
                    </div>
                    <div class="col-sm-7 col-md-8 col-xl-9">
                        <input asp-for="@orderOnline.OrderDate" class="form-control form-control-sm" value="" type="text" autocomplete="off" required />
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-sm-5 col-md-4 col-xl-3">
                        <label asp-for="@orderOnline.OrderId">
                        </label>
                    </div>
                    <div class="col-sm-7 col-md-8 col-xl-9">
                        <input asp-for="@orderOnline.OrderId" class="form-control form-control-sm" value="" required />
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col text-center">
                        <button type="submit" class="btn btn-default"><strong>Submit</strong></button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

Index.cshtml – Date Range Picker

The Date Range Picker plugin is applied to the OrderDate form field and an event is added to re-validate the form when the date is changed.

<script>
	$('#orderOnline_OrderDate').daterangepicker({
		singleDatePicker: true,
		showDropdowns: true,
		autoUpdateInput: false,
		locale: {
			format: 'DD/MM/YYYY'
		}
	});

	$('#orderOnline_OrderDate').on('apply.daterangepicker', function (ev, picker) {
		var orderDate = picker.startDate;
		$(this).val(orderDate.format('DD/MM/YYYY'));

		var validator = $("#OrderOnlineForm").validate();
		validator.element('#orderOnline_OrderDate');
	});
</script>

Index.cshtml – jQuery Validation

The jQuery Validation plugin expects to be working with Bootstrap 3 rather than Bootstrap 4 so the first piece of code updates the plugin defaults to make it work correctly with the new classes.

Two additional rules “maxDate” and “validDate” are then added and applied to the OrderDate form input.

<script>
	jQuery.validator.setDefaults({
		highlight: function (element) {
			jQuery(element).closest('.form-control').addClass('is-invalid');
		},
		unhighlight: function (element) {
			jQuery(element).closest('.form-control').removeClass('is-invalid');
		},
		errorElement: 'div',
		errorClass: 'invalid-feedback',
		errorPlacement: function (error, element) {
			if (element.parent('.input-group').length) {
				error.insertAfter(element.parent());
			} else {
				error.insertAfter(element);
			}
		}
	});

	$.validator.addMethod('maxDate', function (value, element) {
		if (this.optional(element)) {
			return true;
		}

		var selectedDate = moment(value, 'DD/MM/YYYY')
		maxDate = moment().subtract(30, 'days');

		return selectedDate <= maxDate;
	}, 'Order must have been placed more than 30 days ago.');

	$.validator.addMethod("validDate", function (value, element) {
		return this.optional(element) || moment(value, "DD/MM/YYYY").isValid();
	}, "Please enter a valid date in the format DD/MM/YYYY");

	$('#OrderOnlineForm').validate({
		rules: {
			'orderOnline.OrderDate': {
				required: true,
				maxDate: true,
				validDate: true
			}
		}
	});
</script>

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *