11

I'm trying to execute CSOM functions as part of a JSLink extension to override rendering of a Lookup Field.

Problem is every time I try to access SP.ClientContext it returns as undefined

I have tried calling an executeOrDelayUntilScriptLoaded operation to load the context, but my JSLink "rendering" functions always execute WAY before this actually does anything.

SP.SOD.executeOrDelayUntilScriptLoaded(loadContext, 'sp.js');

function loadContext() {
    context = SP.ClientContext.get_current();
    web = context.get_web();
}

If I try putting my JSLink callback functions inside this then they never actually work (and I just get OOB rendering).

hatch.testRender = function (ctx) {
    alert(context); // always returns "undefined"
}
2
  • the function retrieves ctx, I think you should use alert(ctx) command.
    – Alexander
    Aug 16, 2013 at 12:16
  • 1
    No the context (ctx) object in a JSLink function is different to the ClientContext object Aug 17, 2013 at 20:53

8 Answers 8

12

SharePoint 2013 CSR OnPreRender handler could used for initialization of ClientContext since OnPreRender is called before the actual View/Fields rendering

Example:

(function () {   


    function OnPreRenderDocItemTemplate(renderCtx) {
        SP.SOD.executeOrDelayUntilScriptLoaded(loadContext, 'sp.js');
        function loadContext() {
            var context = SP.ClientContext.get_current();
            var web = context.get_web();
        }
    }


    function RegisterDocViewTemplate() {

        var viewContext = {};
        viewContext.Templates = {};
        viewContext.Templates.OnPreRender = OnPreRenderDocItemTemplate; 
        SPClientTemplates.TemplateManager.RegisterTemplateOverrides(viewContext);
    }
    ExecuteOrDelayUntilScriptLoaded(RegisterDocViewTemplate, 'clienttemplates.js');

})();
3

I worked around this problem by having the custom render function return just a placeholder HTML element, and using a $(window).load handler to later populate the element with content obtained through JSOM calls.

By the time the handler executes, the necessary JavaScript libraries have already been loaded, and SP.ClientContext is also available.

1
  • Yes, I suppose this would be the workaround. I ended up using REST calls instead using standard AJAX methods Sep 28, 2013 at 18:23
2

I experienced the same issue using JSLink in O365 Sharepoint Online. My solution was to call my function requiring SP.ClientContext as follows:

//Perform SP.ClientContext tasks after sp.js is loaded
window.onload = function() { SP.SOD.executeFunc('sp.js','SP.ClientContext', someFunction()); };
1

Adding another answer to this question with yet another solution:

Instead of messing around with ExecuteOrDelayUntilScriptLoaded or SP.SOD.executeFunc, I simply added the JSOM files that I needed to get loaded into my JSLink.

So for instance, I needed to use the SP.WorkflowServices namespace. In order to use that, according to this MSDN page, the required files are:

  • SP.js
  • SP.Runtime.js
  • SP.WorkflowServices.js

And of course they have to be loaded in order. So my JSLink for the particular field I'm overriding looks like:

clienttemplates.js|sp.js|sp.runtime.js|sp.workflowservices.js|~site/path/to/my-csr-script.js

And whatever framework is handling loading the JSLink files respects the order, so the files get loaded correctly, and I can use SP.WorkflowServices in my CSR override code.

0

Try this:

SP.SOD.executeFunc('sp.js','SP.ClientContext',loadContext);

function loadContext() {
    context = SP.ClientContext.get_current();
    web = context.get_web();
}
1
  • As I put in my original post something like that works but if I try to include it in my JSLink render functions then my custom rendering gets ignored by SharePoint. If I put it outside of the JSLink render functions then it doesn't execute in time (so is always undefined during rendering) Aug 17, 2013 at 20:52
0

I had a similar problem. It worked well when I moved all my SP.ClientContext code inside the onInit event. You need to register onInit event and call CSOM inside that event. This event executes once all controls are loaded ..

0

The problem I have had with SP.ClientContext undefined was problem with the load library.

My solution did reference to MicrosoftAjax on cloud and not my solution.

I believe when you build a SharePoint solution, itself did it.

I solved changing the references. I downloaded library and add into the my solution, another words, there are not references out solution.

0

I ran into this problem also.

I suspected what was happening was that while the code is delaying for 'SP.js' to load, 'clientTemplates.js' is running full steam ahead and calls RenderListView() before the code can execute RegisterTemplateOverrides().

My answer to this was to leverage @Aveenav's answer to overriding the BaseViewId on Using Different BaseViewID values for multiple JSLink on a single page

(function(){
    //Delay the execution of RenderListView until sp.js is loaded
    ExecuteOrDelayUntilScriptLoaded(function() {
         //Take a copy of the existing Microsoft Definition of RenderListView
         var oldRenderListView = RenderListView;

         //Now delay the execution of the rest of RenderListView until sp.js is loaded
         RenderListView = function(ctx,webPartID) {
             ExecuteOrDelayUntilScriptLoaded(function() {
                 oldRenderListView(ctx,webPartID);
             }, 'sp.js');
         }
    }, 'ClientTemplates.js');
    // Continue with Template Overrides
})();

Testing this showed that I had access to SP.ClientContext within the onPostRender() function (which was where I needed it.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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