Search code examples
knockout.jscustom-binding

Knockout custom format to attributes to more than one


I took a custom binding from Freeman's Pro Javascript for WebApps which basically adds a prefix and/or suffix to an attribute

ko.bindingHandlers.formatAttr = {
    init: function(element, accessor) {
        $(element).attr(accessor().attr, composeString(accessor()));
    },
    update: function(element, accessor) {
        $(element).attr(accessor().attr, composeString(accessor()));
    }
};

Using this javascript function

function composeString(bindingConfig) {
    var result = bindingConfig.value;
    if (bindingConfig.prefix) {
        result = bindingConfig.prefix + result;
    }
    if (bindingConfig.suffix) {
        result += bindingConfig.suffix;
    }
    return result;
}

It works fine as for example

<input data-bind="formatAttr: { attr: 'id', prefix: 'InterestedParty_', suffix: '__Id', value: $data.Guid }" type="hidden"/>

But how could I achieve to make it work for two different attributes in the same input? I've tried some things but either fails or just take the last one. I could create one custom one for each property but then I would lose the generality of it.

Thanks


Solution

  • You can extend your binding handler with the help of some jQuery to work also with arrays:

    ko.bindingHandlers.formatAttr = {
        init: function(element, accessor) {
            var value = accessor();
            if (!$.isArray(value))
                value = [value]
    
            $.each(value, function(index, item){
                $(element).attr(item.attr, composeString(item));
            });
    
        },
        update: function(element, accessor) {
            var value = accessor();
            if (!$.isArray(value))
                value = [value]
    
           $.each(value, function(index, item){
                $(element).attr(item.attr, composeString(item));
           });
        }
    };
    

    So now you can pass an array of { attr, prefix, suffix, value } object as a parameter to your binding:

    <input data-bind="formatAttr: [
       { attr: 'id', prefix: 'InterestedParty_', suffix: '__Id', value: $data.Guid },
       { attr: 'name', prefix: 'Other_', suffix: '__Name', value: $data.Name }]"
       type="hidden" />
    

    Demo JSFiddle.