Knockout.js - cross iframe observable binding
I would like to use knockout.js in an iframe crossover. The existence of the iframe is dictated by the actual structure of the application I am working on.
This is the scenario (simplified):
- Main Window: Knockout.js enabled.
window.top.DATA
- a global container for data, for example.var DATA = { username: ko.observable('John') };
- Iframe module window: Knockout.js is also included. View wants to display the data stored in the object
window.top.DATA
using the code:<div data-bind="text: window.top.DATA.username></div>
What's the result?
DIV's innerHTML contains ko.observable().toString()
content instead of John
.
Cause
Knockout.js cannot recognize the observable created in the parent frame when doing the binding, because the knockout checks if the variable is observable via ko.hasPrototype
reference comparison. Since prototypes are different between parent and child frames ko
, it is not possible to bind values.
Solutions
The simplest solution would be to write something like: window.ko = window.top.ko || setupKO()
at the top of the script file. Unfortunately, in this case, the binding is both with: window.someLocalObj
referenced window.top
instead window
- we cannot access local variables as well as local templates using the binding template
.
Another way to fix the problem is to simply let the knockout recognize the observables as they should, which will allow the observers to track the addiction, link values, and just work well. Unfortunately, I expect this to be difficult to achieve. What options do you see here?
Thanks for all your answers.
Edit
Knockout.js version: 3.2.0.
source to share
One solution is to use a single instance ko
to simultaneously manage the main window and its frame elements. Items are iframe
not available through window.frames[frame_index].document
:
var DATA = { username: ko.observable('John') };
ko.applyBindings(DATA);
ko.applyBindings(DATA, window.frames[0].document.body);
Working example: Plunker
source to share