Focus the First Input In Any Bootstrap Modal

If you’re accepting user input in a bootstrap modal, or you just want to be more friendly to your keyboard-based users, here’s how to focus the first input element on any bootstrap modal in a global context.

$(document).on('shown.bs.modal', function (e) {
     $(e.target).find(":input").not(".close").filter(":visible:first").focus();
});

A few things are happening here:

  • A delegate event listener is placed on the document (preferably in your jQuery document ready function)
  • The event shown.bs.modal is triggered when a bootstrap modal is opened
  • We find the modal element triggering this function with e.target
  • We exclude the (X) close button from being selected
  • We focus the first visible input element (text, button, etc.) 

The nice thing about doing it this way is it applies to all popup modals across the board. It’s an easy one-size-fits-all solution for large applications!

Easy Reset Button for Form Values with Kendo UI and jQuery

Here is a short and sweet all-JavaScript way to create a reset button on a form with a mixture of Kendo UI controls and HTML controls.

var form_cancel_values = [];

// On form load - Save current values of form controls into an array
function readCancelValues() {
    form_cancel_values = $('#UserForm').serializeArray();
}

// User clicked cancel - Reset all form fields to value in array
function recallCancelValues() {
    $("#UserForm [type='checkbox']").prop("checked", false);

    $.each(form_cancel_values, function () {
        if (kendo.widgetInstance($('#' + this.name))) {
            kendo.widgetInstance($('#' + this.name)).value(this.value);
        } else {
            $('#' + this.name).val(this.value).prop("checked", true);
        }
        $('#' + this.name).blur(); // clear Kendo validator tooltip
    });
}

When recalling the cancellation values, first all checkboxes in the form are cleared. Any checked checkboxes will be re-checked later. This is due to the default HTML behavior of checkboxes- they are not defined unless checked.

Using kendo.widgetInstance here allows us to set the value of the Kendo control, regardless of the type of control. That way we don’t concern ourselves with whether it is a DatePicker, ComboBox, etc.

The final touch is to trigger the blur (lose focus) event on each control, so that any “This field is required” Kendo validator tooltips are hidden.

Making an image uploader with Kendo UI and MVC

The Telerik documentation for the Kendo MVC file uploader only covers the basics for this control. Here is a more complete example on how you might set up an image uploader, with error handling, and saving the image data.

The Razor syntax for my upload control using MVC server wrappers looks like this:

@(Html.Kendo().Upload()
    .Name("ImageUpload")
    .Messages((m => m.Select("Select image file...")))
    .Multiple(false)
    .Events(events =>
    {
        events.Error("image_file_failure");
        events.Select("image_file_select");
        events.Success("image_display_refresh");
        events.Upload("image_file_upload");
    })
    .Async(a => a
        .Save("ImageSave", "Home")
        .AutoUpload(true)
    )
    .HtmlAttributes(new { accept = "image/*" })
)

The HtmlAttribute above sets the default type of file the user can select from their system. The user can change it to “All Types” though, so we’ll need to validate their choice is a file type we can accept.

The JavaScript events below add extra data parameters to the upload (image_file_upload), validate the file type (image_file_select), and handle errors from the server (image_file_failure).

    function image_file_upload(e) {
        e.data = { UserId: @Model.UserId };
    }

    function image_file_select(e) {
        var acceptedFiles = [".jpg", ".jpeg", ".png", ".gif", ".bmp"];
        var isAcceptedImageFormat = ($.inArray(e.files[0].extension, acceptedFiles)) != -1;

        if (!isAcceptedImageFormat) {
            e.preventDefault();
            errorMessage = "Image file must be one of the following types: JPG, JPEG, PNG, GIF, BMP";
            alert(errorMessage);
        }
    }

    function image_file_failure(e) {
        var _error;
        if (e.XMLHttpRequest.status == 500) {
            _error = "Server Error: " + $(e.XMLHttpRequest.responseText).filter('title').text();
        } else {
            _error = e.XMLHttpRequest.responseText;
        }

        errorMessage = "There was an error uploading the image file. " + _error;
        alert(errorMessage);
    }

In my case I would receive a 500 server error when the file size exceeded several megabytes, and the server would return an entire error page in XMLHttpRequest.responseText. I’m reporting the title of that error page to the user with jQuery.

The MVC controller that accepts the uploaded file needs a HttpPostedFileBase parameter with the same name as your Kendo Upload control, in this case ImageUpload.

        public ActionResult ImageSave(HttpPostedFileBase ImageUpload, int UserId)
        {
            var _Model = new ImageModel();
            return Content(_Model.Save(ImageUpload, UserId));
        }

The Kendo Upload control is expecting an empty string to be returned to it upon success. Any other text means an error has occurred.

Now the image data can be converted into the image format of your choice with the System.Drawing.Imaging library, and copied into a byte stream for inserting into your database. Here is the Save method that does that in my model.

        public string Save(HttpPostedFileBase ImageUpload, int UserId)
        {
            var _Result = ""; // Kendo uploader expects empty string on success

            if (ImageUpload != null)
            {
                try
                {
                    // Read image file
                    Image _Image = Image.FromStream(ImageUpload.InputStream);

                    // Encode image data as Gif image byte array
                    MemoryStream _ImageMemoryStream = new MemoryStream();
                    _Image.Save(_ImageMemoryStream, ImageFormat.Gif);
                    byte[] _ImageBytes = _ImageMemoryStream.ToArray();

                    // Insert byte array data in database
                    var _Success = SavePhoto(UserId, _ImageBytes);

                    if (!_Success)
                    {
                        _Result = "Error saving image to database";
                    }
                }
                catch (Exception ex)
                {
                    _Result = "Error reading image data: " + ex.Message;
                }
            }
            else
            {
                _Result = "Upload Error: Empty file data";
            }

            return _Result;
        }

Get ID when a custom command is clicked in Kendo grids

Quick code tip for getting the row data from a custom command button in Kendo UI grids. This is useful for intercepting a delete event or any custom actions you have set up on a Kendo grid.

    function grid_deleterow(e) {
        var row = $(e.currentTarget).closest("tr");
        var data = $("#grid").data("kendoGrid").dataItem(row);
        var id = data.EntityId;
    }

In the JavaScript function above, id will contain the value of the EntityId column for the row of the custom button clicked. This is great because you don’t have to make your grid selectable for this to work.

Here is how the event would be triggered when using the Kendo MVC wrappers:

        @(Html.Kendo().Grid<EntityModel>()
             .Name("test_grid")
             .Columns(columns =>
             {
                 columns.Bound(p => p.Field1);
                 columns.Command(command => command.Custom("Delete").Click("grid_deleterow"));
             })
           )

Validating Bootstrap radio buttons with Kendo UI

Validating radio buttons isn’t supported by the Kendo form validator. Add Bootstrap radio buttons in the mix and you’ve got double the reason to roll your own validation! Fortunately we can use a little jQuery to require the user to select a radio button, and set the chosen value for form submission. Here’s the JavaScript I came up with, triggered on form submit:

$(function () {

    // On form submit, validate and send form by ajax
    $(document).on("click", ":submit", function (event) {

        // Custom validation for required bootstrap radio buttons
        if ($('#radiobuttons').children().filter("[class~='active']").length < 1) {
            $("#validator_msg").show();

        } else {
            $("#validator_msg").hide();
            
             // Set hidden field equal to the chosen radio button's text
            $("#radiovalue").val(
                $('#radiobuttons').children().filter("[class~='active']").text().trim()
             );
             // Submit form by ajax elsewhere
             submit_ajax();
        }

        // Prevent default navigation
        return false;
    });
});

The related HTML uses Bootstrap radio buttons, and emulates the Kendo validator tooltip to alert the user that the field is required:

                                    <!--Hidden radio button field set on submit -->
                                    <input type="hidden id="radiovalue">
                                    <div class="btn-group" data-toggle="buttons" id="radiobuttons" onclick="$('#validator_msg').hide();">
                                        <label class="btn btn-primary">
                                            <input type="radio"> Pineapple
                                        </label>
                                        <label class="btn btn-primary">
                                            <input type="radio"> Coconut
                                        </label>
                                        <label class="btn btn-primary">
                                            <input type="radio"> Lime
                                        </label>
                                    </div>
                                    <!-- Custom kendo tooltip for required radio buttons -->
                                    <span class="k-widget k-tooltip k-tooltip-validation k-invalid-msg field-validation-error" id="validator_msg" role="alert" style="display: none">
                                        <span class="k-icon k-warning"> </span> Please select a value
                                    </span>

Now when you attempt to submit the form without selecting a radio button, you should see the Kendo validation tooltip prompting you for required input!

Single click checkbox editing for Kendo grids

This is possibly the most anti-climatic code ever. You click a checkbox in a column, and click the save button. It just works. Except that’s not a default behavior supported in Kendo UI. Depending on how you do it, you either have to click into the cell, then the click the checkbox, or maybe your checkbox value won’t save at all.

The goal here is to have a grid column displayed as checkboxes for boolean values. The problem is the checkbox displayed isn’t connected to the data structure behind the Kendo Grid.

Telerik has an example of checkbox column editing, but it’s hard coded with a grid id, column name, and checkbox class. We need something that can be applied to all grids in an application!

Behold…


// On jQuery document ready
jQuery(function ($) {

    // Synchronize the kendo grid data to user clicked checkbox value
    // This is necessary for single-click grid editing on checkboxes for the checkbox state to be saved properly
    // This delegate event handler applies to all kendo grids
    $("body").on("click", "td", function(e) {

        // Get the parent grid from the cell clicked
        var grid = $(this).closest(".k-grid").data().kendoGrid;

        // Get the selected row and column from the cell clicked
        var row = $(this).closest("tr");
        var colId = $("td", row).index(this);

        // Get the column binding name from the grid properties
        var colBinding = grid.options.columns[colId].field;

        // Look for an enabled checkbox input inside the cell clicked
        var chk = $(this).children("input[type=checkbox]:enabled");
        if (chk.length) {

            // Get the Kendo data structure which keeps track of grid edits for the chosen row
            var dataItem = grid.dataItem(row);

            // FINALLY: Set the boolean data value to the checkbox value in the cell clicked
            dataItem.set(colBinding, chk[0].checked);

        }
    });
});

Now any grid in your application will allow the user to click into the checkbox directly, and save the grid.

Checkboxes in a Kendo grid

If you’re still stuck on how to get a checkbox showing in a Kendo grid column in the first place, here’s how to do it with ASP.NET MVC wrappers:

columns.Bound(p => p.IsActive).ClientTemplate("<input type='checkbox' #= IsActive ? checked='checked' : '' # />");