0

I am currently having an odd problem with my optionsText within a multi-select list I am building with Knockout.

I noticed that some of the text data that I am retrieving from my controller is HTML encoded and I would like to have it displayed properly within my select list.

Simple Example

String from my controller (and how it's currently displaying)

Dave & Buster

How I would like it displayed

Dave & Buster

I tried to use a function in the optionsText to perform the decoding without creating a computed, but for some reason, the decode didn't work at all.

html-data-bind="options: ViewModel.AvailableItems, 
   optionsText: function(item) { return decodeURI(item.Label()) }, 
   optionsValue: 'Value', 
   selectedOptions: ViewModel.ItemsSelected"

I am currently populating my view model using the the Knockout Mapping plug-in, so that is a big reason I didn't use computeds to resolve this. This way I don't have to mess with mapping settings any time the model gets additional properties.

I tried using the optionsAfterRender binding with the following code (Fiddle I found it from and the question I found it from)

ViewModel.setOptionHTML = function(option, html) {
    ko.applyBindingsToNode(option, {
        html: html
    })
}

However, when the optionText is rendered, it shows up as [object][object].

What am I missing in order to get my text to display properly in my select list?

Here is an example to show the issue:

var vm = {
    ViewModel: { 
        AvailableItems: [
            {
                Label: ko.observable("Dave & Buster"),
                Value: 1
            }
        ],
        ItemSelected: ko.observable()
    }
};

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select data-bind="options: ViewModel.AvailableItems, 
   optionsText: function(item) { return decodeURI(item.Label()) }, 
   optionsValue: 'Value', 
   selectedOptions: ViewModel.ItemsSelected">
</select>
Community
  • 1
  • 1
Exitium
  • 133
  • 11
  • [I cannot reproduce your issue](http://jsfiddle.net/svcskudn/). Please edit your question and include a full but minimal repro. (PS. The `decodeURI` function is for *URI*-encoded things, but "`&`" is *html*-encoded.) – Jeroen Sep 24 '15 at 21:37
  • I added an update with the proper example. You were close, but the input comes oddly encoded from my controller. – Exitium Sep 24 '15 at 21:48
  • Can you please post your model. If your getting [object][object] back it suggests to me that your item.label isn't a raw string, but a collection of objects. Wow I was like 1 second late to ask for that – Michael Crook Sep 24 '15 at 21:48

1 Answers1

2

This is one way to do it. the only issue being that it's not inclusive of every escape character that is out there, so you would either have to add every one OR just have a limited set that you accept

EDIT: See code snippet under this, it SHOULD de-encode everything :)

var vm = {
    ViewModel: { 
        AvailableItems: [
            {
                Label: ko.observable("Dave &amp; Buster"),
                Value: 1
            }
        ],
        ItemSelected: ko.observable()
    }
};

deEncode = function(raw){
  return raw.replace(/&amp;/g, '&').replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
}

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select data-bind="options: ViewModel.AvailableItems, 
   optionsText: function(item) { return deEncode(item.Label()) }, 
   optionsValue: 'Value', 
   selectedOptions: ViewModel.ItemsSelected">
</select> 

Edit: did some more searching of the interwebs and found this gem:

I would say this is better:

var vm = {
    ViewModel: { 
        AvailableItems: [
            {
                Label: ko.observable("Dave &amp; Buster"),
                Value: 1
            }
        ],
        ItemSelected: ko.observable()
    }
};

deEncode = function(raw){
  return $("<div/>").html(raw).text()
}

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>


<select data-bind="options: ViewModel.AvailableItems, 
   optionsText: function(item) { return deEncode(item.Label()) }, 
   optionsValue: 'Value', 
   selectedOptions: ViewModel.ItemsSelected">
</select> 
Source of cool jquery code: How to decode HTML entities using jQuery?
Community
  • 1
  • 1
Michael Crook
  • 1,520
  • 2
  • 14
  • 37