knockoutjs container less template inside SELECT,

2019-02-20 04:01发布

问题:

I have an quiz/survey application and I'm having problems populating a dropdown list using knockoutjs.

Please check this fiddle with Firefox (or Chrome), then try it with Internet Explorer 9 (or IE8, or IE7... knockout says to be compatible from IE6+ but obviously IE gives some problems in my scenario).

In Firefox and Chrome my jsfiddle example works , but not with Internet Explorer. See in thab 1, last question "Where do you live?" and in tab 2, "Favorite sport?". The dropdown is not populated in IE.

I suspect that something is not working well with $parent, or $parent.ParticipantAnswer == null is not understood by IE. I tried to debug but obviously didn't find the cause, so here I am.

In both tab1 and tab2, the options are not populated, so here the code where these 2 templates are called:

<!-- ko if: AnswerTypeId == 2 -->
<select data-bind="attr: { name: Id, id: 'answerq' + Id }">
<option value="0"></option>
<!-- ko template: { name: 'option-template', foreach: Answers } -->                                                        
<!-- /ko -->
</select>
<!-- /ko -->

<!-- ko if: AnswerTypeId == 6 -->
<select data-bind="attr: { name: Id, id: 'answerq' + Id }">
    <option value="0"></option>
    <!-- ko template: { name: 'location-template', foreach: Answers } -->                                                        
    <!-- /ko -->
</select>
<!-- /ko -->

And here the 2 templates:

<script type="text/html" id="option-template">

    <!-- ko if: $parent.ParticipantAnswer != null && $parent.ParticipantAnswer.AnswerId == $data.Id -->
    <option data-bind="text: Description, attr: { value: Id, selected: 'selected' }"></option>
    <!-- /ko -->

    <!-- ko if: ($parent.ParticipantAnswer == null || $parent.ParticipantAnswer.AnswerId != $data.Id) -->
    <option data-bind="text: Description, attr: { value: Id }"></option>
    <!-- /ko -->

</script>

<script type="text/html" id="location-template">

    <!-- ko if: $parent.ParticipantAnswer != null && $parent.ParticipantAnswer.AnswerInt == $data.Id -->
    <option data-bind="text: Description, attr: { value: Id, selected: 'selected' }"></option>
    <!-- /ko -->

    <!-- ko if: ($parent.ParticipantAnswer == null || $parent.ParticipantAnswer.AnswerInt != $data.Id) -->
    <option data-bind="text: Description, attr: { value: Id }"></option>
    <!-- /ko -->              

</script>

I was thinking that a container less template would create problems, but this jsfiddle works on both Firefox and IE.

I really have no idea why it doesn't work with IE, I'm asking here for a valid fix and maybe an explanation of the cause, so we all can learn from it ;) Thank you.

回答1:

In general, containerless bindings work fine in Internet Explorer. However, IE (at least before 10) strips comments in certain scenarios like inside of select elements.

So, KO never sees the comments or has a chance to process them. One of your best bets is to use the repeat binding: https://github.com/mbest/knockout-repeat. This will basically let you do a foreach by attaching to the element to be repeated rather than a container.