jQWidgets Forums
jQuery UI Widgets › Forums › Dialogs and Notifications › Window › Bind docking windows to knockout observableArray?
Tagged: binding, docking, JavaScript, jQuery, jqwidgets, jqxDocking, knockoutjs, mvvm, window
This topic contains 3 replies, has 2 voices, and was last updated by Minko 13 years, 1 month ago.
-
Author
-
Hi,
I was wondering if it was currently possible to display a total of 12 windows with each window having the same thing so I would like to use a template. What I was wondering is if I could bind to an observableArray in knockout like so:
<div id='jqxWidget'> <div id="docking"> <div> <div data-bind="template: { name: 'person-template', foreach: people }"> </div> </div> </div> </div> <script type="text/html" id="person-template"> <div id="Header"><h3 data-bind="text: name"></h3></div> <div id="Content"><p>Credits: <span data-bind="text: credits"></span></p></div> </script>
and then in the javascript:
function MyViewModel() {
this.people = [
{ name: 'Franklin', credits: 250 },
{ name: 'Mario', credits: 5800 }
]
}
ko.applyBindings(new MyViewModel(), $("#jqxWidget").get(0));
$("#docking").jqxDocking({ width: 250, theme: 'classic' });
And this would generate windows based on the number of items in the observable array.
Thanks,
JonHello John,
For your aim you have to add a custom render which handles new added windows, when the observableArray is changed.
In this render you have to add an id to the window and add it to the docking.
In the source bellow there’s a better illustration of my description.You can achieve the searched effect this with the following JavaScript:
var theme = 'classic', PeopleModel = function () { //We define observable variable for the name this.personName = ko.observable(); //We define observable variable for the credits this.personCredits = ko.observable(); //We define observable array for the pairs (name, credits) this.people = ko.observableArray([{ name: 'Franklin', credits: 250 }, { name: 'Mario', credits: 5800}]); var self = this, sectionsCount = 0, windowsCount = 0, maxSections; //This method will handle the new added sections function handleSection(el) { var id = 'knockout-section-' + sectionsCount; sectionsCount += 1; el.id = id; } //This method will handle the new added windows function handleWindow(el) { var id = 'knockout-window-' + windowsCount, section = windowsCount % sectionsCount; windowsCount += 1; $(el).attr('id', id); $('#docking').jqxDocking('addWindow', id); $(el).detach(); $(el).appendTo($('#knockout-section-' + section)); } //We define the docking's sections count to be equal to the startup count of the objects in the //people array. This is not mandatory but it's important to create all different sections before the docking initialization maxSections = this.people().length; //This method handles adding a new person (when the user click on the Add button) this.addPerson = function () { if (this.personName() && this.personCredits()) { this.people.push({ name: this.personName(), credits: this.personCredits() }); } } //This custom render takes care of adding new windows this.buildWindow = function (element) { var el = element[1]; if (sectionsCount < maxSections) { handleSection(el); handleWindow($(el).children('.knockout-window')); } else { handleWindow($(el).children('.knockout-window')); $(el).remove(); } } };ko.applyBindings(new PeopleModel());$('#docking').jqxDocking({ theme: theme, orientation: 'horizontal', width: 380, mode: 'docked' });});
Using this HTML5 markup:
<input type="text" data-bind="value: personName" /><input type="text" data-bind="value: personCredits" /><input type="button" data-bind="click: addPerson" value="Add" /><div id='jqxWidget'> <div id="docking" data-bind="template: { foreach: people, afterRender: buildWindow }"> <div class="knockout-section"> <div class="knockout-window"> <div>Name <span data-bind="text: name"></span></div> <div> Credits count: <span data-bind="text: credits"></span> </div> </div> </div> </div></div>
Best regards,
Minko
jQWidgets Team
http://www.jqwidgets.com/Hi Minko,
Thanks for the code, however, I get a knockout exception: Unable to get value of the property ‘nodeType’: object is null or undefined
This is what I have:
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <link rel="stylesheet" href="jqwidgets-ver1.9/jqwidgets/styles/jqx.base.css" type="text/css" /> <!-- add the jQuery script --> <script type="text/javascript" src="jqwidgets-ver1.9/scripts/jquery-1.7.1.min.js"></script> <!-- add the knockout script --> <script type="text/javascript" src="jqwidgets-ver1.9/scripts/knockout-2.0.0.js"></script> <!-- add the jQWidgets framework --> <script type="text/javascript" src="jqwidgets-ver1.9/jqwidgets/jqxcore.js"></script> <!-- add one or more widgets --> <script type="text/javascript" src="jqwidgets-ver1.9/jqwidgets/jqx-all.js"></script> <!-- add my javascript script --> <script type="text/javascript">
var theme = 'classic',
PeopleModel = function () {
this.people = ko.observableArray([{ name: 'Franklin', credits: 250 }, { name: 'Mario', credits: 5800}]);var self = this,
sectionsCount = 0,
windowsCount = 0,
maxSections;
//This method will handle the new added sections
function handleSection(el) {
var id = 'knockout-section-' + sectionsCount;
sectionsCount += 1;
el.id = id;
}
//This method will handle the new added windows
function handleWindow(el) {
var id = 'knockout-window-' + windowsCount,
section = windowsCount % sectionsCount;
windowsCount += 1;
$(el).attr('id', id);
$('#docking').jqxDocking('addWindow', id);
$(el).detach();
$(el).appendTo($('#knockout-section-' + section));
}
//We define the docking's sections count to be equal to the startup count of the objects in the
//people array. This is not mandatory but it's important to create all different sections before the docking initialization
maxSections = this.people().length;
//This method handles adding a new person (when the user click on the Add button)
this.addPerson = function () {
if (this.personName() && this.personCredits()) {
this.people.push({
name: this.personName(),
credits: this.personCredits()
});
}
}
//This custom render takes care of adding new windows
this.buildWindow = function (element) {
var el = element[1];
if (sectionsCount < maxSections) {
handleSection(el);
handleWindow($(el).children('.knockout-window'));
} else {
handleWindow($(el).children('.knockout-window'));
$(el).remove();
}
}
};ko.applyBindings(new PeopleModel());
$('#docking').jqxDocking({ theme: theme, orientation: 'horizontal', width: 380, mode: 'docked' });</script> <title></title></head><body> <form id="form1" runat="server"> <div id="main"> <div id='jqxWidget'> <div id="docking" data-bind="template: { foreach: people, afterRender: buildWindow }"> <div class="knockout-section"> <div class="knockout-window"> <div>Name <span data-bind="text: name"></span></div> <div> Credits count: <span data-bind="text: credits"></span> </div> </div> </div> </div> </div> </div> </form></body></html>
Thanks,
JonHello Jon,
I’m sorry that I missed that issue. It seems that KnockoutJS is passing different parameters to the buildWindow function in IE8.
Here is the code with that issue fixed:$(document).ready(function () { var theme = 'classic', PeopleModel = function () { //We define observable variable for the name this.personName = ko.observable(); //We define observable variable for the credits this.personCredits = ko.observable(); //We define observable array for the pairs (name, credits) this.people = ko.observableArray([{ name: 'Franklin', credits: 250 }, { name: 'Mario', credits: 5800}]); var self = this, sectionsCount = 0, windowsCount = 0, maxSections; //This method will handle the new added sections function handleSection(el) { var id = 'knockout-section-' + sectionsCount; sectionsCount += 1; el.id = id; $(el).appendTo($('#docking')); $(el).css('width', '47%'); } //This method will handle the new added windows function handleWindow(el) { var id = 'knockout-window-' + windowsCount, section = windowsCount % sectionsCount; windowsCount += 1; $(el).attr('id', id); $('#docking').jqxDocking('addWindow', id, 'docked', section, windowsCount); } function getDOMElement(args) { for (var i = 0; i < args.length; i += 1) { if (args[i].tagName && args[i].tagName.toUpperCase() === 'DIV') { return args[i]; } } return null; } //We define the docking's sections count to be equal to the startup count of the objects in the //people array. This is not mandatory but it's important to create all different sections before the docking initialization maxSections = this.people().length; //This method handles adding a new person (when the user click on the Add button) this.addPerson = function () { if (this.personName() && this.personCredits()) { this.people.push({ name: this.personName(), credits: this.personCredits() }); } } //This custom render takes care of adding new windows this.buildWindow = function (element) { var el = getDOMElement(element); if (sectionsCount < maxSections) { handleSection(el); handleWindow($(el).children('.knockout-window')); } else { handleWindow($(el).children('.knockout-window')); $(el).remove(); } } }; ko.applyBindings(new PeopleModel()); $('#docking').jqxDocking({ theme: theme, orientation: 'horizontal', width: 380, mode: 'docked' });});
Best regards,
Minko
jQWidgets Team
http://jqwidgets.com/ -
AuthorPosts
You must be logged in to reply to this topic.