Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Durandal JS knockout Deferred updates

I am having an issue when enabling deferred updates in the knockout library. I have implemented Jquery datatables as a component, when navigating to a view that has this component i can see the following methods being called in order. Getview>Activate>Attach

everything works as expected

But if i press f5 and refresh the page rather than navigating to it from another page it breaks and the following methods are called

Getview>Activate>Attach>Getview>Activate>Attach>Detach>Detach (not sure why its called twice in the end) and it breaks, no table shows on the UI at all as it does not render from what i can tell, i think it has something to do with durandal transitions and there being a difference between navigating to a page and refreshing a page kinda grasping at straws tho.

This is a minimal class that replicates the problem for me, note i dont have an HTML file for this component i want to use the getView method to pass in some dynamic HTML from JQueryDT

I created a quick sample project with the bare minimum needed to replicate the problem. https://bitbucket.org/dchosking1988/deferred-update-example

If you pull that and run it you will see that the "hello world" will disappear when you refresh the page but it wont if you navigate between tabs.

the general steps i used to replicate the issue are

1) download sample project

2) add test component (see repo above for the sample file)

3) enable deferred updates

4) disable view caching

4) try compose new instance of the component

Edits to give more info

*This is not a JQuery Datatable problem, it is replicated with the following

So you dont have to download the gitRepo, this is the code i can replicate the problem with in the sample project following the above steps.

define([],
function () {
    var test = function () {
        var self = this;

        var defaultViewHtml = '<div> <h1>Hello World</h1></div>';
        var currentView = null;

        self.getView = function () {
            console.log('GetView');
            if (!currentView) {
                currentView = $(defaultViewHtml)[0];
            }
            return currentView;
        };

        self.activate = function (activateOptions) {
            console.log('Activate');
        };

        self.attached = function (view, parent, settings) {
            console.log('Attatched');
        };

        self.detached = function (view, parent) {
            console.log('Detatched');
        };
    };

    return test;
});

Then Add this HTML to the index.html, also dont forget to create an instance of the class in the index.js

 <div class="whiteRow">
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <div data-bind="compose: { model: test }"></div>
            </div>
        </div>
    </div>
</div>
like image 327
Darryn Hosking Avatar asked Jun 02 '17 14:06

Darryn Hosking


2 Answers

This is occurred because it call code twice and second called the currentView stay empty in test.js, I commented the stretch where you set the currentView and code work.

self.getView = function () {
               console.log('GetView');
               //if (!currentView) {
               //    currentView = $(defaultViewHtml)[0];
               //}
               return currentView;
               };

-

<div class="whiteRow">
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <div data-bind="compose: { model: test }"></div>
            </div>
        </div>
    </div>
</div>
like image 96
Igor Paiva Avatar answered Oct 21 '22 04:10

Igor Paiva


define([],
function () {
var test = function () {
    var self = this;

    var defaultViewHtml = '<div> <h1>Hello World</h1></div>';
    var currentView = null;

    self.getView = function () {
           console.log('GetView');
           return currentView;
           };

    self.activate = function (activateOptions) {
        console.log('Activate');
    };

    self.attached = function (view, parent, settings) {
        console.log('Attatched');
    };

    self.detached = function (view, parent) {
        console.log('Detatched');
    };
  };

  return test;
});

currentView stay empty in test.js,

like image 31
Kondal Avatar answered Oct 21 '22 06:10

Kondal