2
votes

It seems that when using Knockout's text binding, multiple spaces become collapsed into one. For example:

<textarea data-bind="value: Notes"></textarea>
<p data-bind="text: Notes"></p>

function VM() { this.Notes = ko.observable(); }

var vm = new VM();

ko.applyBindings(vm);

Here is a fiddle to demonstrate this: http://jsfiddle.net/9rtL5/

I am finding that in jsfiddle, the spaces are compacted in Firefox, Chrome and IE9. Strangely though within my app IE9 does not compact them, but the others do.

My understanding is that Knockout uses an HTML text node to render the value. I found this related question on preserving spaces when creating a text node:

http://www.webdeveloper.com/forum/showthread.php?193107-RESOLVED-Insert-amp-nbsp-when-using-createTextNode%28%29

Should Knockout handle transforming spaces appropriately? I don't really want to use a custom binding handler for this.

I actually came across this in the context of the display text within a select, and only discovered that it also relates to a simple text binding while debugging that issue. I presume the select issue is the same.

1

1 Answers

1
votes

What you are observing is normal behavior. When rendered in certain elements, the whitespace is trimmed. Knockout shouldn't be doing any automatic replacements, if I wanted to send a string to a server with leading/trailing spaces using knockout, it better make it there with those spaces.

You should create a binding handler to replace the spaces with no-breaking spaces so it can be rendered that way.

ko.bindingHandlers.spacedtext = {
    replaceSpace: function (str) {
        return new Array(str.length + 1).join('\xA0');
    },
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var spacedValue = ko.computed(function () {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                text = value && value.toString();
            return text && text.replace(/^\s+|\s+$/gm, ko.bindingHandlers.spacedtext.replaceSpace);
        });
        ko.applyBindingsToNode(element, { text: spacedValue });
    }
};

Demo