jQWidgets Forums

jQuery UI Widgets Forums Dialogs and Notifications Window Bind docking windows to knockout observableArray?

This topic contains 3 replies, has 2 voices, and was last updated by  Minko 13 years, 1 month ago.

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author

  • jonr
    Member

    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,
    Jon


    Minko
    Blocked

    Hello 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/


    jonr
    Member

    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,
    Jon


    Minko
    Blocked

    Hello 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/

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.