Hello and thanks for taking a look.
I have a dynamic survey with a pretty deep hierarchy:
<assessment>
<criterionTypes>
<criterionType>
<criteria>
<criterion>
<responses>
<response>
<assessmentResponses>
<assessmentResponse>
Occasionally, I would have some of the observable items in the array not bind to the form in the proper order.
This despite my iterating over that collection, adjusting the sort before handing it over to the view and even seeing that list in the proper order in the Chrome debugger. I was able to resolve this by applying a sort routine into the foreach for those collections that weren't well behaved. Like so:
<!-- ko foreach: criterionTypes -->
<div data-bind="foreach: criteria.sort($root.context.sort.criteria),
or
<!-- ko foreach: assessmentResponses.sort(function (l, r) { return (l.id() == r.id()) ? (l.id() > r.id() ? -1 : 1) : (l.id() > r.id() ? -1 : 1) }) ... -->
So far so good. However, I have a function where a user can add a new row, and while the model gets updated in knockout, the UI will not reflect those changes. So if I drop the sort, the model binding works and the UI updates as expected.
In my update button I have tried to rebind in my click event:
var addResponse = function (response) {
core.addResponse(assessment(), response);
ko.applyBindings(assessment);
};
But I wind up with the same error regardless of what object I try to bind (assessment, response, etc)
Uncaught Error: Unable to parse bindings. Message: ReferenceError: router is not defined; Bindings value: compose: {model: router.activeItem, afterCompose: router.afterCompose, transition: 'entrance'}
I'm not sure how I might proceed with this. Perhaps a custom binding that would perform the sort on the foreach, but I couldn't get that sorted out (pun-intended).
<div id="boolean.secondaryResponse" data-bind="if: isSecondaryResponse(), visible: $parent.showSecondaryResponse()>
<!-- ko foreach: assessmentResponses.sort(function (l, r) { return (l.id() == r.id()) ? (l.id() > r.id() ? -1 : 1) : (l.id() > r.id() ? -1 : 1) }) -->
<!-- ko if: customResponse().template() == 'ingredientSource'-->
<div class="col-md-2 col-lg-2" style="z-index: 10"><select data-bind="value: explanation, options: $root.controls.ingredientOrigins, event: { change: $root.context.selectionChanged }, attr: { class: 'form-control ' + criterionCode() + ' ordinal-' + customResponse().ordinal() } " class="remove"></select> </div>
<!-- /ko -->
<!-- ko if: customResponse().template().startsWith('span')-->
<div data-bind="attr: { class: customResponse().template() + ' col-sm-2 col-md-4' }" style="margin-left: -10px; z-index: 10; height: 69px"><input type="text" data-bind="value: textualResponse, attr: { class: 'form-control auto' + customResponse().name() + ' ordinal-' + customResponse().ordinal(), placeholder: customResponse().placeholder }" class="remove" /></div>
<!--/ko -->
<!-- /ko -->
<!-- /ko -->
</div>