7

With Client Object Model API and a bit of javascript, I want to retrieve the items of a sharepoint list and display them into the web page, when the web page loads.

I've successfully implemented examples working with button or link click event handler. But when I try to use the code with onload I get an error.


Assuming I've my ViewItem() function defined in the head.

If I use this code in the body:

  <a onclick="javascript:ViewItem()">View</a>

all is fine.

If I try with classic onlaod, the call fails:

 <script type="text/javascript">
  window.onload = ViewItem ;
 </script>

The line of code in ViewItem function which generates the error is as follows:

   var myContext = new SP.ClientContext.get_current();

This code works fine with the onclick event handler, but fails with the onload event handler with error:

SP.ClientContext is null or not an object

How can I solve this issue? Why it happens only when the function is called with onload?


I've tried managing the onload with ExecuteOrDelayUntilScriptLoaded as suggested by the answers below, but no success. The behavior is as follows now:

The onclick works fine.

As soon as I add the code ExecuteOrDelayUntilScriptLoaded in the HTML body, the ViewItem function does not get executed and the onclick returns the error message which I've described in my initial question.

If I remove the onclick and leave the onload only, no error is returned but the ViewItem does not get executed.


I've found that it works fine with jQuery only. Don't know why.

Code Details: https://gist.github.com/1744459

4 Answers 4

11

The reason why you get the SP.ClientContext is null or not an object error is because when you call your function on window.onload event, the sp.js file is not loaded on the page yet. The sp.js file contains all the code for the Client Object Model and hence your code is not able to find the SP.ClientContext object.

The solution is pretty simple. Call you function like this:

<script type="text/javascript">
  window.onload = function(){ ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js"); };
</script>

The ExecuteOrDelayUntilScriptLoaded function makes it sure that your ViewItem function is executed only after the sp.js file is completely loaded on the page.


The accepted (working) solution is as by the comments jQuery:

$(document).ready(function(){ ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js"); });
7
  • 2
    Do you have jQuery with you? you can try: $(document).ready(function(){ ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js"); }); instead of the window.onload Commented Feb 5, 2012 at 9:33
  • Also, it would be great if you could post your code here. Commented Feb 5, 2012 at 9:35
  • Code posted. Thanks it works with jQuery!!! Why only with jQuery??? See gist.github.com/1744459 for details. Commented Feb 5, 2012 at 9:56
  • I have a look at your code and I think the window.onload should be inside the ContentPlaceHolder with ID PlaceHolderAdditionalPageHead. Currently, it is in the ContentPlaceHolder with Id PlaceHolderMain Commented Feb 5, 2012 at 10:15
  • 1
    @Andrey You can always do ExecuteOrDelayUntilScriptLoaded(function(){ ViewItem(param1,param2); }, "sp.js"); Commented Feb 14, 2014 at 19:45
7

SharePoint 2010 introduces new feature named Script On Demand. It means that almost all scripts in sharepoint loaded on demand. In your situation you access to SP.ClientContext that is declared in sp.js, which is not loaded yet. Special function exists to wait until particular js file is loaded - ExecuteOrDelayUntilScriptLoaded. This function accepts two arguments - function and script name. If script with specified name already loaded, function will be called immediately, if not, it will be called as soon as script will be loaded.

Your code using this notes should look like:

window.onload = function(){
    ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js");
}

And some more notes. If you want to run some js code after page load, preferable way to use shaerpoint built-in mechanism (or jQuery if possible) which involves using _spBodyOnLoadFunctionNames array. This array contains function names that will be called after body loaded. So, updated code:

function myfunc(){
  ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js");
}
_spBodyOnLoadFunctionNames.push("myfunc");
10
  • Have you tried to use _spBodyOnLoadFunctionNames as I described? Commented Feb 5, 2012 at 9:40
  • I've just tested it - it is not working with window.onload, but is working with _spBodyOnLoadFunctionNames Commented Feb 5, 2012 at 9:54
  • Thanks for your time. It works only with jQuery. See gist.github.com/1744459 for details. Are you able to tell me why? Commented Feb 5, 2012 at 9:56
  • 1
    I've tested, it works, could you please post your code, how do you use it? And if any javascript errors appears? Commented Feb 5, 2012 at 10:12
  • 1
    @empo, I'm not arguing to this :) However, personally I used _spBodyOnLoadFunctionNames tens of times (if not hundreds) and I know that it is a workable solution. Thus I assume that something is wrong with your environment/code/whatever. For example, you don't need referencing sp.js with <SharePointWebControls:ScriptLink Name="SP.js" runat="server" OnDemand="true" Localizable="False" />, and this code could be the one who causes the issue. Anyway, since it is not my answer, I'd prefer to leave further explorations and testing to @Kai :) Commented Feb 5, 2012 at 10:54
0

I would suggest that you shouldn't use the window.onload(); instead try and use this.

$(document).ready(function() 
 {
    // executes when HTML-Document is loaded and DOM is ready
    ExecuteOrDelayUntilScriptLoaded(ViewItem, "sp.js");
    alert("(document).ready was called - document is ready!");  
 });  

Hope this fixes the issue.

0

Using window.onload in a modular application like SharePoint is not a good practice, as the latest window.onload will overwrite all others. My take is that it is your issue here.

Instead, SharePoint implements a built-in mechanism to pile up onload functions (as explained by Kai). I would expect this to work (not tested):

_spBodyOnLoadFunctionNames.push(function(){ExecuteOrDelayUntilScriptLoaded(ViewItem,"sp.js");});

Your Answer

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

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