knockout-switch-case
knockout-switch-case copied to clipboard
Embedded Knockout-Switch with Let Binding Overwrites $caseValue on child context then breaks the UI
Original issue reported on knockout issues: https://github.com/knockout/knockout/issues/2550.
Hi,
I spent the weekend tracking down a insidious issue on our enterprise-scale application that is based on Knockout.js. I finally was able to create a minimal reproducible example on jsfiddle. Situation:
- Outer knockout-switch structure.
- Let binding block within the active case statement in the outer switch structure.
- Inner switch statement within the let binding context.
- Change a condition that causes one of the case statements on the inner switch statement to go to false.
- Outer switch structure fails, and none of its case blocks, including the $default case block, are rendered, leaving the user interface blank.
What I see happening in the knockout code:
When the condition is changed, the child context is updated via ko.bindingContext updateContext method. This ends up calling: ko.utils.extend(self, parentContext);
This copies all properties from the parent contexts to the child context. The $caseValue binding context variable from the outer context gets overwritten in the inner case binding context. THEN the inner case binding sets its $caseValue to false (which is now pointing to the outer switch case binding $caseValue), thus causing the outer switch binding's case statements to permanently go to false, including the $default.
This seems like a bug to me, but could possibly a misuse / misunderstanding of the let binding. It seems like the inner binding context's $caseValue properties should never be overwritten by an outer switch binding's $caseValue properties, regardless of the presence of a let binding.
At any rate, it's a pitfall because binding context mutation is happening unintentionally that is causing undesirable behavior, and extremely difficult to track down. Please see this fiddle for a very simple demo of the problem:
https://jsfiddle.net/gsdLyftc/10/