9

If you look at below code, I have used executeordelayuntillscriptloaded at start of my script so that it will run only after that file is loaded. But this breaks some functionality. Can you check this code and tell me if its not good practice?

It was done so that the SP.Utilities.Utility.getLayoutsPageUrl functionality never throw undefined error:

 <SharePoint:ScriptLink ID="ScriptLink1" name="SP.js" runat="server"
    ondemand="false" localizable="false" loadafterui="true" />
<SharePoint:ScriptLink ID="ScriptLink2" name="SP.UserProfiles.js" runat="server"
    ondemand="false" localizable="false" loadafterui="true" />

<script type="text/javascript">
SP.SOD.executeOrDelayUntilScriptLoaded(runthiscode, 'SP.js');

function runthiscode()
{
    var personProperties;

    // Ensure that the SP.UserProfiles.js file is loaded before the custom code runs.    

    SP.SOD.executeOrDelayUntilScriptLoaded(getUserProperties, 'SP.UserProfiles.js');

    function getUserProperties() {  

        // Get the current client context and PeopleManager instance.
        var clientContext = new SP.ClientContext.get_current();
        var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

        // Get user properties for the target user.
        // To get the PersonProperties object for the current user, use the
        // getMyProperties method.
        personProperties = peopleManager.getMyProperties();

        // Load the PersonProperties object and send the request.
        clientContext.load(personProperties);
        clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
    }

    // This function runs if the executeQueryAsync call succeeds.
    function onRequestSuccess() {       

        if (personProperties.get_userProfileProperties().CustomPropertyValue == "False") {

          window.location(SP.Utilities.Utility.getLayoutsPageUrl('')+'someurl.aspx');

        }

    }

    // This function runs if the executeQueryAsync call fails.
    function onRequestFail(sender, args) {
        var r = confirm("There was an error, the page will reload");

              window.location(SP.Utilities.Utility.getLayoutsPageUrl('')+'someurl.aspx'); 
    }

 function someotherfunction() {

        window.location.href = SP.Utilities.Utility.getLayoutsPageUrl('')+'someotherurl';

    }
}
</script>
4
  • if your code depends on some other js file, I would call it a must more than a best practice. This is the documented way in SharePoint to wait for a script (with ondemand="false") to be fully loaded before executing some custom code that depends on it.
    – MdMazzotti
    Commented Apr 4, 2014 at 10:48
  • Is my above code best practice? what happens turning ondeamnd=on (just asking).
    – variable
    Commented Apr 4, 2014 at 10:49
  • I would recommend that you read this post here on SP.SE: sharepoint.stackexchange.com/a/58509/8642
    – MdMazzotti
    Commented Apr 4, 2014 at 10:53
  • Use SP.SOD.executefunc('sp.js','SP.ClientContext',runthiscode);
    – Unnie
    Commented Apr 4, 2014 at 11:23

3 Answers 3

11

Use SP.SOD.executeFunc('sp.js','SP.ClientContext',runthiscode); instead of SP.SOD.executeOrDelayUntilScriptLoaded. because SP.SOD.executefunc makes sure the file is loaded and then executes the method and SP.SOD.executeOrDelayUntilScriptLoaded will only put the method on queue untill the file is loaded(so if file is not loaded then never executes). SP.SOD.executeFunc loads on demand scripts, so script link should be added for that js file.

<SharePoint:ScriptLink ID="ScriptLink2" name="SP.UserProfiles.js" runat="server"
    ondemand="false" localizable="false" loadafterui="true" />
     <script type="text/javascript">
        SP.SOD.executeFunc('sp.js','SP.ClientContext',runthiscode);
        function runthiscode()
        {

                // Ensure that the SP.UserProfiles.js file is loaded before the custom code runs.    
                SP.SOD.executeFunc('SP.UserProfiles.js','SP.UserProfiles',getUserProperties);
       }
        var personProperties;
            function getUserProperties() {  

                // Get the current client context and PeopleManager instance.
                var clientContext = new SP.ClientContext.get_current();
                var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

                // Get user properties for the target user.
                // To get the PersonProperties object for the current user, use the
                // getMyProperties method.
                personProperties = peopleManager.getMyProperties();

                // Load the PersonProperties object and send the request.
                clientContext.load(personProperties);
                clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
            }

            // This function runs if the executeQueryAsync call succeeds.
            function onRequestSuccess() {       

                if (personProperties.get_userProfileProperties().CustomPropertyValue == "False") {

                  window.location(SP.Utilities.Utility.getLayoutsPageUrl('someurl.aspx');

                }

            }

            // This function runs if the executeQueryAsync call fails.
            function onRequestFail(sender, args) {
                var r = confirm("There was an error, the page will reload");

                      window.location(SP.Utilities.Utility.getLayoutsPageUrl('someurl.aspx'); 
            }



        </script>
6
  • sorry but how can it make sure that it is loaded if we are not specifiying it in head tag to load it? is it true?
    – variable
    Commented Apr 4, 2014 at 11:41
  • 1
    SP.js is loaded by sharepoint by default. SP.SOD.executefunc('SP.UserProfiles.js','SP.UserProfiles',getUserProperties); will explicitly load this file if already not loaded. So you don't have to load it by using script link in head.
    – Unnie
    Commented Apr 4, 2014 at 11:55
  • Ok, cool, is the logic same if this code would go on a masterpage instead of an application page?
    – variable
    Commented Apr 5, 2014 at 5:00
  • Also, the last function 'someotherfunction' (its a href javascript on an <a href= tag) uses SP.Utilities.Utility.getLayoutsPageUrl, so dont you think this as well needs to go under execute func?
    – variable
    Commented Apr 5, 2014 at 5:04
  • If I use your technique then the code wont run, I tested by putting an alert box, under runthiscode(), it doesnt show up.!
    – variable
    Commented Apr 5, 2014 at 7:59
4

Prefer SP.SOD.executeFunc over SP.SOD.executeOrDelayUntilScriptLoaded

Since SP.SOD.executeFunc supports load on demand scripts, there is no need to reference explicitly SP JavaScript files using SharePoint:ScriptLink

The following example demonstrates how to initialize UserProfiles CSOM in application page:

SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() {
   // Make sure PeopleManager is available 
   SP.SOD.executeFunc('userprofile', 'SP.UserProfiles.PeopleManager', function() {

      var clientContext = new SP.ClientContext.get_current();
      var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

      //...

   });

});

Usage of SP.Utilities.Utility.getLayoutsPageUrl

SP.Utilities.Utility.getLayoutsPageUrl(pageName) Method accepts pageName as a parameter.

Example: how to get Settings page url

var pageUrl = SP.Utilities.Utility.getLayoutsPageUrl("Settings.aspx");
5
  • SP.Utilities.Utility.getLayoutsPageUrl needs to be under SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() { ?
    – variable
    Commented Apr 4, 2014 at 11:39
  • that's correct since SP.Utilities.Utility.getLayoutsPageUrl is a part of SP.js Commented Apr 4, 2014 at 11:46
  • Now I will place the entire js code under SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() { // Make sure PeopleManager is available SP.SOD.executeFunc('userprofile', 'SP.UserProfiles.PeopleManager', function() {
    – variable
    Commented Apr 4, 2014 at 12:05
  • @VadimGremyachev "no need to reference explicitly SP JavaScript files using SharePoint:ScriptLink": if in a custom page I know beforehand that I'm going to need some js file, then I think it perfectly makes sense to explicitly load it via ScriptLink. In the end, that's why they provided two different functions: they serve different needs
    – MdMazzotti
    Commented Apr 5, 2014 at 9:24
  • @MdMazzotti I agree with you Commented Apr 5, 2014 at 10:58
2

It is not necessary to use the SP.SOD.executeFunc function to declare a dependency with an unwieldy callback function.

Instead you should just register a dependency for the function you are calling using the RegisterSodDep function.

For the original example:

RegisterSodDep('runthiscode', 'sp.js');
RegisterSodDep('runthiscode', 'SP.UserProfiles.js');
SP.SOD.executeFunc('SP.UserProfiles.js', null, runthiscode); 

runthiscode will not be called until the two dependencies have been loaded.

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.