[CLOSED] Error with Partial Views

Page 2 of 3 FirstFirst 123 LastLast
  1. #11
    Hello!

    When I mentioned 'break on handled exceptions' I was thinking on the browser's debugger.

    This is how it looks like in Chrome:
    Click image for larger version. 

Name:	60656_01-chrome_exceptions.png 
Views:	39 
Size:	6.7 KB 
ID:	24450

    And this is how it looks like in IE11:
    Click image for larger version. 

Name:	60656_02-ie11_exceptions.png 
Views:	24 
Size:	12.4 KB 
ID:	24451

    In fact, you may try to run without VS debugging (Debug menu > Start without debugging), as it is not catching any exceptions anyway. I personally prefer to handle javascript-side debugging on the browser's debuggers. Visual studio has an history of breaking (or stalling for minutes) when you accidentally break on a minified, large javascript file.
    Fabrício Murta
    Developer & Support Expert
  2. #12
    Hi Fabricio

    Thanks for the guidance, very helpful. I've now managed to trap the error but I've still no idea what the cause/solution is!

    I've managed to replicate it twice and both times it was the same:

    Click image for larger version. 

Name:	IE Error screen 1.jpg 
Views:	26 
Size:	92.1 KB 
ID:	24453

    Thanks

    Jeff
  3. #13
    It again looks like a race condition, but without being able to reproduce the issue locally, it is really hard to give good advice.

    It looks like a control is being attempted to be destroy()ed after it -- or parts of it -- have already been destroyed. I think you should try to simplify the page iteractively until you can isolate the error and provide us a sample reproducing it. I understand you already stated as this is not trivial, but I can't see much way out of this problem if not being able to isolate it.
    Fabrício Murta
    Developer & Support Expert
  4. #14
    Hi Fabricio

    From all the evidence I have I think you're right; it's trying to render the partial view before the content has been cleared. Before I replicate it for you to look at it I would like to try something.

    This is the function which renders the partial view:

                var loadView = function (button, viewName, url) {
                    var panel = App.PnlCenter,
                        loader = panel.loader;
    
                    panel.clearContent();
                    var leftMenuButtons = App.LeftMenuPanel.query();
                    Ext.each(leftMenuButtons, function (button) {
                        button.el.setStyle('border-color', 'lightgrey');
                    });
                    button.el.setStyle('border-color', 'black');
                    loader.url = url;
                    loader.params = {
                        containerId: loader.target.getBody().id,
                        viewName: viewName
                    };
    
                    panel.load();
                };
    Would it be possible to insert a while loop after the
                    panel.clearContent();
    Something like

    panel.clearContent();

    While panel.contents not clear

    delay timer

    ?

    Thanks

    Jeff
  5. #15
    Hello Jeff!

    Well, one simpler way would be just to delay executing the rest of the code, wrapping it on another function, using the Ext.createDelayed() function. Something like (not tested!):

                var loadView = function (button, viewName, url) {
                    var panel = App.PnlCenter,
                        loader = panel.loader;
    
                    panel.clearContent();
    
                    var restOfFunction = function(button, viewName,url) {
                        var leftMenuButtons = App.LeftMenuPanel.query();
                        Ext.each(leftMenuButtons, function (button) {
                            button.el.setStyle('border-color', 'lightgrey');
                        });
                        button.el.setStyle('border-color', 'black');
                        loader.url = url;
                        loader.params = {
                            containerId: loader.target.getBody().id,
                            viewName: viewName
                        };
    
                        panel.load();
                    };
    
                    Ext.createDelayed(restOfFunction, 2000, this);
    
                };
    I'm not sure clearContents() should be running async tasks that would allow it to return before everything is in place, although every possibility must be taken. But one thing that may very well happen is:
    - you call a direct method with a callback function that, for example, clears the contents.
    - before the callback is actually called, you do something relying on the contents to be already cleared

    Due to internet unstability, the callback may never be called in the end (lost packets, etc). Usually you'll hit an ajax timeout and an error dialog will be displayed -- when the call is to be totally lost. But the timeout is something between 10 and 30 seconds, enough time to not trigger any warning, yet run something before an ajax call returns with pre-requisites done.

    But, in general, for a testing environment you should be good with the 2000ms wait (2 seconds) just to be sure you wait any overhead (even unexpected) to happen. Maybe also, as you are clicking repeatedly to reproduce the issue, your interval between clicks being quite fast, and being caught by garbage collection in-between, may then be the "timer bomb" to trigger the race condition.

    You mentioned it happening after several clicks here, just for reference.

    You may set UI semaphores to avoid race conditions by, for example, if you click a button repeatedly to reproduce your issue, then make your method look like something like this:
    var loadView = function (button, viewName, url) {
        var panel = App.PnlCenter,
            loader = panel.loader;
    
        button.disable(); // Prevent the button to be clicked repeatedly!
    
        panel.clearContent();
        var leftMenuButtons = App.LeftMenuPanel.query();
        Ext.each(leftMenuButtons, function (button) {
            button.el.setStyle('border-color', 'lightgrey');
        });
        button.el.setStyle('border-color', 'black');
        loader.url = url;
        loader.params = {
            containerId: loader.target.getBody().id,
            viewName: viewName
        };
        loader.success = function () {
            var button = App.myButton; // the scope might be different, there's a way to pass the current button, but left as exercise :)
            button.enable();
        }
    
        // re-establish the button's clickability if the load process fails as well
        loader.failure = function () {
            var button = App.myButton;
            // do something to ensure the whole page is not in a very inconsistent state -- if something was already changed and required the callback
            // refreshing the whole page may be an option on such cases!
            button.enable();
        }
    
        panel.load();
    };
    Fabrício Murta
    Developer & Support Expert
  6. #16
    Hi Fabricio

    Thanks for your detailed response. I do need to resolve this but I'm focusing on completing some other functionality at the moment. I'll get back to you when I've tried some or all of your suggestions.

    Thanks again

    Jeff
  7. #17
    Hi Fabricio

    I'm trying to implement your suggestion but I get the error
    Object doesn't support property or method 'createDelayed'
    Regards

    Jeff
  8. #18
    Sorry, the correct syntax is Ext.Function.createDelayed()!
    Fabrício Murta
    Developer & Support Expert
  9. #19
    Hi Fabricio

    Thanks for that. In fact it should be:

    Ext.Function.createDelayed(restOfFunction, 2000, this)();
    with () at the end.

    That works up to a point but then the parameters in restOfFunction are undefined. Presumably it loses the initial values of button, viewName and url because of the delay. Apologies again for my lack of javascript knowledge but I'm not sure how to overcome this.

    Thanks

    Jeff
  10. #20
    Hello Jeff!

    I've written this small example, I hope it helps you understand and put it to good use. I've dropped the this parameter because it may just bring confusion. It is useful to keep the context of the component when the function is called from a Listener event trigger.

    var chain1 = function (a, b, c) {
                console.log("Chain1");
                logTime(a, b, c);
                var delayedChain2 = Ext.Function.createDelayed(chain2, 1500);
    
                delayedChain2(a, b, c);
            }
    
            var chain2 = function (a, b, c) {
                console.log("Chain2");
                logTime(a, b, c);
                var delayedChain3 = Ext.Function.createDelayed(chain3, 1500);
    
                delayedChain3(a, b, c);
            }
    
            var chain3 = function (a, b, c) {
                console.log("Chain3");
                logTime(a, b, c);
            }
    
            chain1('arg1', 'arg2', 'arg3');
    Here, you can just replace 'arg1' to 'arg3' with the values or references you want to pass ahead for button and the view name. And also maybe something else depending on the stage.

    Just paste this code on a developer tools' console tab. You should currently be on an Ext.NET page (so Ext.Function is valid).
    Fabrício Murta
    Developer & Support Expert
Page 2 of 3 FirstFirst 123 LastLast

Similar Threads

  1. [CLOSED] ViewData and partial views
    By ingbabic in forum 2.x Legacy Premium Help
    Replies: 4
    Last Post: Jan 20, 2016, 12:01 PM
  2. [CLOSED] Window in Partial Views
    By Istofix in forum 2.x Legacy Premium Help
    Replies: 1
    Last Post: Mar 06, 2014, 3:18 PM
  3. [CLOSED] Javascript Error on Same IDs in multiple partial views
    By PriceRightHTML5team in forum 2.x Legacy Premium Help
    Replies: 6
    Last Post: Mar 05, 2014, 8:50 AM
  4. [CLOSED] [Razor] using partial views
    By machinableed in forum 2.x Legacy Premium Help
    Replies: 1
    Last Post: Apr 25, 2012, 9:40 AM
  5. Replies: 0
    Last Post: Oct 15, 2009, 6:07 AM

Posting Permissions