4

Disclaimer I am working on an edge case here. The Javascript file is dynamically created server-side, and the JSLinks all point to the same absolute URL (receiving different content). JSLink Absolute URLs are only possible on Office365/SharePoint Online


I have a View with CSR file

window.a='a';
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
  var b='b';
  function init() {
    var c='c';
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
      OnPostRender: function(ctx) { 
        try{
            console.log('OnPostRender',window.a,b,c);
            console.log(_spPageContextInfo.serverRequestPath);
        }catch(e){
            console.error(e);
        }
      },
      ListTemplateType: 101
    });
  }
  RegisterModuleInit(SPClientTemplates.Utility.ReplaceUrlTokens("~siteCollection/Style Library/csr.js"), init);
  init();
});
  • When I open this page all is fine
  • When I browse to another page (remember MDS is enabled)
  • And then return to the View
  • ... my globals are gone ... (a is undefined in the second OnPostRender)

everything I defined as global is gone.

If I define b as window.b its destroyed as well.

Now this is a pain because I used JSLink to load a suporting library.. in the global scope.

Note #1

Global functions are not destroyed (all the CSR examples out there are based on functions)

Note #2

Yes, there is

Problem I have: My JS file is dynamically created by a PHP script (and also used by non-SharePoint sites), so it has the same filename but different content

But, after a sleepless night, I am getting there...

5

I don't think this is necessarily an edge case because it is easy to reproduce the issue and as it turns out, the behaviour is expected.

It might be helpful if you have an on-prem version of SP13 available so you can step through the code in start.debug.js to see what's going on.

I noticed your reference to Hugh Wood's excellent blog post Part 4 - Async Delta Manager but I found the clue in Part 3 - Minimal Download Strategy

Here's a screenshot of part of that post

Screenshot

So with this information I set my SharePoint web app to use the debug versions of the js files, opened up start.debug.js, and this is what I found.

enter image description here

You'll notice on line 2979 that a loop is entered that loops through each member of the window object, checks whether it is a function, undefined, contained in an array called _snapshot, or a namespace.

If none of those conditions are satisfied, on line 2989 the member is set to undefined and deleted (I set a conditional breakpoint on memberIdx=='a' in order to watch your window.a variable be blown away)

So, that explains how your global is disappearing, I guess the next step is to work out how to "register" your global into the _snapshot array so that it is skipped over during this cleanup process.

UPDATE

So the AsyncDeltaManager._snapShot array is populated in start.js on lines 2170, where a copy of each global variable name is saved to the array. This snapshot of the globals is taken only once, the first time the MDS delta is retrieved. If your own global is not declared and populated by then, it looks like it misses out!

enter image description here

SOLUTION

The supported workaround would simply be to store your globals on a namespace, where they won't get get blown away.

Type.registerNamespace("Foo");
Foo.a='a';

SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
  var b='b';
  function init() {
  var c='c';
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
    OnPostRender: function(ctx) { 
      try{
          console.log('OnPostRender',Foo.a,b,c);
          console.log(_spPageContextInfo.serverRequestPath);
      }catch(e){
          console.error(e);
      }
    },
    ListTemplateType: 101
  });
}
RegisterModuleInit(SPClientTemplates.Utility.ReplaceUrlTokens("~siteCollection/Style Library/csr.js"), init);
init();
});

Hope that helps!

  • 2
    TNX!! Yes, I made it work with RegisterNamespace ... although I waisted hours on the server side stuff, 301 redirects... well.. not waisted.. learned a lot.. BTW created DOM elements are not removed by MDS... Causing me a head-egg; I am almost there with a tool that can drop JS-Link easter-eggs all over the place – Danny '365CSI' Engelman Mar 20 '16 at 8:27
  • Nice, I'll keep an eye out for your tool, I've been considering writing such a thing myself too. – Paul Lucas Mar 20 '16 at 8:41
  • Click the egg after you have created the 365csi.nl/jsl Bookmarklet (I am coding live against these files). the pronounciation of the english letter ** I ** sounds the same as the dutch 'ei' which is dutch for 'egg' .. hence the head-egg coding this :-) – Danny '365CSI' Engelman Mar 20 '16 at 8:51
  • So.... all the lines like var jslinkOverride = window.jslinkOverride || {}; in PnP: github.com/OfficeDev/PnP/… and many blogs are doing nothing – Danny '365CSI' Engelman Mar 20 '16 at 9:02
  • Cool! Yeh not sure about the PnP stuff, I really need to dive into that a bit more. – Paul Lucas Mar 20 '16 at 21:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.