TL;DR Answer
ko.bindingHandlers.nl2br = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var field = ko.utils.unwrapObservable(valueAccessor());
field = field.replace(/\n/g, '<br />');
ko.bindingHandlers.html.update(element, function() { return field; });
}
};
Full Answer
First things first, the replace
call should probably be:
field = field.replace(/\n/g, '<br />');
Otherwise the new string gets discarded.
Apart from that, I wouldn't recommend setting the element value like that directly. Rely on the existing handlers (that presumably are well tested in various browsers) to do the heavy lifting. See R.P. Niemeyer's blog post on the subject (specifically item 3).
You can use either the the text
binding which will literally render "<br />
" or (if you trust the input!) the html
binding if you want to render a newline for the <br />
. The latter looks like this:
ko.bindingHandlers.nl2br = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var field = ko.utils.unwrapObservable(valueAccessor());
field = field.replace(/\n/g, '<br />');
ko.bindingHandlers.html.update(element, function() { return field; });
}
};
ko.applyBindings({ description: ko.observable("This is\nSparta!") });
p, pre { background-color: #dde; margin: 4px 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<strong>Text version in <p>:</strong>
<p data-bind="text: description"></p>
<hr />
<strong>Text version <pre>:</strong>
<pre data-bind="text: description"></pre>
<hr />
<strong>NL2BR version in <p>:</strong>
<p data-bind="nl2br: description"></p>