Search code examples
asp.net-mvcasp.net-coreknockout.jstextareaknockout-validation

knockout textarea value binding shows ASCII characters for line breaks?


I have a knockout value binded textarea like so:

<textarea class="form-control" data-bind="value: test" name="test" rows="4"></textarea>

However, when saving data with line breaks or extra spaces, upon next viewing of the page it displays it with the ASCII characters. Like so:

Overview being explained here in this box.&#xA;&#xA;Test stuff test stuff.

When I look at the value in the database it does not have those characters:

Overview being explained here in this box.

Test stuff test stuff.

Indeed even in the view model before the data gets passed to the view everything looks correct:

Overview being explained here in this box.\n\nTest stuff test stuff.

And finally even when first entered, the knockout property pageModel().test() shows the text like this too:

"Overview being explained here in this box.

Test stuff test stuff."

So why does knockout finally render it with the ASCII characters? My KO model looks like this when the value is already input:

self.test = ko.observable('Overview being explained here in this box.&#xA;&#xA;Test stuff test stuff.');

Okay, it's an MVC issue then, because I am calling it like so:

self.test = ko.observable('@Model.Test');

But I can't figure out how to get this to work, if I use Html.Raw the line breaks are interpreted correctly but then that breaks the javascript breaks because there is a space between lines without proper string ending.

I also try just escaping the \r\n characters:

self.test = ko.observable('Overview being explained here in this box.\\n\\nTest stuff test stuff.');

This doesn't remove the problem though, I still get the double &#xA;.

How the heck can I get this working right while still using the value binding? Because I am using knockout.validation, and I could make this work by using html binding and use a slight hack:

<textarea class="form-control" data-bind="value: test, event: { keyup: function(data, event) { data.test(event.target.value); } }" name="test" rows="2"></textarea>

But this completely breaks knockout validation for any textareas because html is a one way binding that doesn't get validated. So I still need to use the value binding.

How to get this working?


Solution

  • You're probably looking for

    self.test = ko.observable('@HttpUtility.JavaScriptStringEncode(ViewBag.Test)');
    

    or as you pointed out for .NET Core you'll need

    @(JavaScriptEncoder.Default.Encode(question.Test))