Handlebars Field Plugin

Handlebars Field Plugin

bradmacgregorbradmacgregor Posts: 9Questions: 0Answers: 0

If you want to create a more complicated custom control with an arbitrary number of inputs or complexity, you might be interested in this plugin which allows you to use a handlebars template to build html with given data.

Here is my plugin for handlebars:

(function ($, DataTable) {
    if ( ! DataTable.ext.editorFields ) {
        DataTable.ext.editorFields = {};
    }
    let editor = DataTable.Editor;

    DataTable.ext.editorFields.handlebars = {
        create: function (conf) {
            // A jquery promise, which when resolved provides the template
            if (typeof conf.templatePromise !== 'object') {
                return undefined;
            }
            if (typeof conf.get !== 'function') {
                return undefined;
            }
            if (typeof conf.set !== 'function') {
                return undefined;
            }

            //create attachment point
            conf._actualId = editor.safeId(conf.id);
            conf._container = $('<div>', {id: conf._actualId});

            //build the control within a div and return it
            conf.templatePromise.done(function (template) {
                conf._template = template;
                conf._container.html(template(conf.data));
                if (typeof conf.init === 'function') {
                    conf.init(conf._container, conf.data);
                }
            });
            return conf._container;
        },
        get: function (conf) {
            return conf.get(conf._container);
        },
        set: function (conf, data) {
            conf.data = data;
            // conf._container.html(conf._template(data));
            return conf.set(conf._container, data);
        },
        input: function (conf) {
            return conf._container;
        },
        update: function (conf, data) {
            //be sure to use delegation for events or rebind them in init
            conf.data = data;
            conf._container.html(conf._template(data));
            if (typeof conf.update === 'function') {
                conf.update(conf._container, data);
                if (typeof conf.init === 'function') {
                    conf.init(conf._container, data);
                }
            }
        }
    };
})(jQuery, jQuery.fn.dataTable);

Here is how you might use it

function getHandlebarTemplate(name, callback) {
    let path = '/assets/handlebars/handlebars_templates/' + name + '.hbs';
    return $.ajax({
        url: path
    }).then(function (source) {
        let template = Handlebars.compile(source);
        if (callback && typeof callback === 'function') callback(template);
        return template;
    });
}

let fields = editor.fields;

fields.push({
    type: 'handlebars',
    label: 'My Custom Field',
    name: 'customField',
    templatePromise: getHandlebarTemplate('myTemplate'),
    get: function (control) { return control.find('input.myClass').val(); },
    set: function (control, data) { control.find('input.myClass').val(data.test); },
    //init is called after template is attached to container (update or create)
    init: function (control, data) {
        //here is where you might bind events or otherwise modify the control
    },
    //field update regenerates source from template, sets into container, and calls this then init
    update: function (control, data) {
        //since editor likes to add this class to all inputs, you might need to do this.
        control.find('div.someClass input.form-control').removeClass('form-control');
    },
    data: {test: 1}
});

You can create a new resolved promise in the case that you want to cache the fetched templates.

https://handlebarsjs.com/

Replies

  • allanallan Posts: 61,451Questions: 1Answers: 10,055 Site admin

    That's superb, thank you for sharing this with us! I really like handlebars, so its great to see this.

    Allan

This discussion has been closed.