jQuery Mask

This field renderer “masks” a field’s value using the jQuery Mask plugin.

The code can be adjusted to use a variety of masks, but this example displays a phone number in the format (000) 000-0000, even if the field value does not match that format.

To use this field renderer, you must include the jQuery Mask plugin as either a generic JavaScript resource or an external JavaScript resource, linking to its code perhaps through a CDN. The example page below includes the unminified code as a snippet.

https://s3.us-west-2.amazonaws.com/developer.skuid.com/assets/v16.4.4/api-versions/v2/skuid/javascript/custom-field-renderers/examples/jquery-mask/./jquery-mask.gif

The jQuery dependency

Because jQuery Mask depends on jQuery, and because JavaScript resource list order determines load order, it’s important that the sample field renderer code appears before the jQuery Mask plugin code. You can see the following concepts illustrated in the sample page below:

  • Skuid ships with jQuery so it isn’t necessary to include it as a JavaScript resource inline or call a CDN. But it only exists on the skuid object, not the window object, where jQuery plugins expect it to be.
  • So in the field renderer code, we set a reference to Skuid’s jQuery on the window object. Because this JavaScript resource is listed first in the JavaScript tab, this code runs first.
  • Finally, after the field renderer code loads, the jQuery Mask code loads. Since jQuery is available on the window object, it functions as expected.

If the jQuery Mask plugin were to load before the field renderer, it would try to look for window.jQuery before it exists. But because the load order is set, we avoid this dependency snafu.

Example Code

Download the sample page for this field renderer here, or see the example code below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// jQuery plugins often assume jQuery is on the window object.
// Skuid includes jQuery 3, so we can set a reference here.
window.jQuery = skuid.$;
const $ = skuid.$
// Alternatively, you can import jQuery as a separate resource.

// To avoid intermingling styles with the logic code below,
// let's create a `styles` object that contains the necessary CSS.
// We can then apply that later on using $(element).css().
const styles = {
    default: {
        "border-color": "#d1d3d5",
    },
    edit: {
        "flex": "auto",
        "background-color": "#fff",
        "border": "1px solid #d1d3d5",
        "border-radius": "3px",
        "box-shadow": "0 0 2px 0 rgba(139,143,149,.12) inset, 0 2px 2px 0 rgba(139,143,149,.24) inset",
        "color": "#4a4f5a",
        "font-family": "Roboto,Helvetica,sans-serif",
        "font-size": "13px",
        "font-weight": "400",
        "padding": "8px",
        "width": "100%",
        "min-width": "48px",
        "position": "relative",
    },
    focused: {
        "border-color": "#005cb9",
    }
};

// We'll need to set the variables used for the jQuery mask plugin.
// There are variety of masks available, such as date time entry or zip code,
// but for this example let's use a phone number mask. For more information,
// see jQuery Mask docs.
let Mask = "(000) 000-0000",
    Reverse = false;

// Now let's build the field renderer itself.
const FieldRenderer = skuid.component.FieldRenderer;
return new FieldRenderer({
    readModeStrategy: "virtual",
    read: function (fieldComponent) {
        let h = fieldComponent.h,
            context = fieldComponent.cpi.getContext(),
            { field, model, row, value } = context;

        return h("div",
            {
                // When working with third party libraries, particularly
                // jQuery plugins, you'll sometimes need to adjust the DOM element.
                // The `afterCreate()` function is essential for this.
                // Here, we'll use it to wrap the element in jQuery,
                // then apply the mask. We'll also set our `default` style
                // rules here.
                afterCreate(element) {
                    $(element).mask(Mask, { reverse: Reverse });
                    $(element).css(styles.default);
                },
            },
            [value],
        )
    },

    editModeStrategy: "virtual",
    edit: function (fieldComponent) {
        let h = fieldComponent.h,
            context = fieldComponent.cpi.getContext(),
            { field, model, row, value } = context;

        return h("input",
            {
                // We'll need to use `afterCreate()`
                // to not just set the mask and the CSS,
                // but also the field's value. Otherwise,
                // the input field would be blank when rendered.
                afterCreate(element) {
                    element.value = value;
                    $(element).mask(Mask, { reverse: Reverse });
                    $(element).css(styles.edit);
                },
                // When the focus event fires, apply the appropriate styles.
                onfocus(event) {
                    $(event.target).css(styles.focused);
                },
                // Here is the basic boiler plate code needed
                // to interface with the field's model, but
                // it's important to note that the
                // alterations made by the mask will also
                // be saved to the field unless you use cleanVal().

                // In this example we use cleanVal() on the element.
                // So, "(555) 555-5555" will save to the model
                // as "5555555555". Alternatively, you could enforce
                // the style from the mask by using `event.target.value`,
                // which would save "(555) 555-5555" as the value.

                oninput(event) {
                  model.updateRow(row,
                    {
                      [field.id]: $(event.target).cleanVal()
                      // [field.id]: event.target.value // To save the masked value.
                    },
                    { initiatorId: fieldComponent.id }
                  );
                },
                onblur(event) {
                    fieldComponent.cpi.onInputBlur();
                },
            },
            [value]
        )
    }
})