0

I am trying to dynamically set the Project UID in an Angular app which is deployed to every subsite throughout my PWA. I need to be able to ideally, store the Project UID in a global variable which I can then use throughout the rest of the app to point to the correct REST api endpoint.

I'm struggling with how I can leverage the function for getting the current site's Project UID which I found here [https://sharepoint.stackexchange.com/questions/224485/project-web-app-get-project-id-from-project-related-site-via-rest], to update the global variable with the Project UID to use in my app controllers. The function works, supposedly, but when I console.log(ProjectUID) I don't get the GUID I'm expecting, instead I get a boolean 'false'.

Any suggestions?

var ProjectUID = ExecuteOrDelayUntilScriptLoaded(getProjectUIDProperty, "sp.js");

function getProjectUIDProperty() { 
  var ctx = new SP.ClientContext.get_current(); 
  console.log(ctx);
  this.web = ctx.get_web(); 
  console.log(this.web);
  this.props =  this.web.get_allProperties(); 
  ctx.load(this.web); 
  ctx.load(this.props);                    
  ctx.executeQueryAsync(Function.createDelegate(this, gotProperty), Function.createDelegate(this, failedGettingProperty)); 
}

function gotProperty() {                
  let ProjectUID = this.props.get_item('MSPWAPROJUID');
}

function failedGettingProperty() { 
  alert('Error: ' + args.get_message());
}
console.log(ProjectUID);


  [1]: https://sharepoint.stackexchange.com/questions/224485/project-web-app-get-project-id-from-project-related-site-via-rest
1

You're probably seeing the result you are seeing because you are not anticipating how the async nature of the code execution is actually happening.

First of all, you are doing something in your initial line of code that is a bit different from the example in the linked question. You have

// you are assigning the return value of ExecuteOrDelayUntilScriptLoaded
// into your ProjectUID variable

var ProjectUID = ExecuteOrDelayUntilScriptLoaded(getProjectUIDProperty, "sp.js");

but the example in the other question has

 var ProjectUID; // full stop.  they are just defining the variable in a scope outside of the other functions

// then they independently call ExecuteOrDelayUntilScriptLoaded
 ExecuteOrDelayUntilScriptLoaded(getProjectUIDProperty, "sp.js");

Regardless, the way you have it still might work, except for where you have your console.log to try and see the resulting project ID. When you are calling that console.log, the result probably hasn't come back from the server yet.

That console.log is after you define the function that calls out to the server to get the project ID, and it is after you define the success callback where you actually get the ID from the web properties, but that does not guarantee that those functions have actually executed by the time you get to your console.log.

Try the following code where I have put in a bunch of additional console.log entries to try to illustrate the code execution order:

var ProjectUID;

console.log('1. calling ExecuteOrDelayUntilScriptLoaded');
ExecuteOrDelayUntilScriptLoaded(getProjectUIDProperty, "sp.js");

function getProjectUIDProperty() {
    console.log('6. getProjectUIDProperty was just called');
    var ctx = new SP.ClientContext.get_current(); 
    this.web = ctx.get_web(); 
    this.props =  this.web.get_allProperties(); 
    ctx.load(this.web); 
    ctx.load(this.props);
    console.log('7. about to make the request to the server to get the web allProperties');
    ctx.executeQueryAsync(Function.createDelegate(this, gotProperty), Function.createDelegate(this, failedGettingProperty)); 
}
console.log('2. finished defining the getProjectUIDProperty function');

function gotProperty() {                
    ProjectUID = this.props.get_item('MSPWAPROJUID');
    console.log('8. finally got my result back from the server:', ProjectUID)
}
console.log('3. finished defining the success call back function');

function failedGettingProperty() {
    console.log('8. oops, got an error instead of a successful result');
    alert('Error: ' + args.get_message());
}
console.log('4. finished defining the failure callback function');

console.log('5. I wish I had my result here, but I dont yet:', ProjectUID);

Additionally:

If you don't want to use the JSOM to get the project ID (personally I am not a big fan of JSOM syntax, with the whole ctx.load, ctx.executeQueryAsync and all that), you can probably get it using a simple REST GET query:

<site url>/_api/web/allProperties?$select=MSPWAPROJUID
4
  • Thanks.. I initially had just set the variable as in the example, but that didn't work either. What I take is that it the value I want is only accessible from the local function gotProperty... not elsewhere. I'll try the simpler REST query! thank you :) – user2004758 Mar 2 at 19:01
  • Well, no, not exactly - it's only available after the result has come back from the server. In the case of the code example given using the JSOM syntax, that happens to be in the success handler (which is named gotProperty). If, in that success handler, you set that value to be somewhere globally accessible in your Angular app, it will be. But again, only after that success handler fires. It's the same with a REST query - you have to wait for the response back from the server before you can use data from that response. – Dylan Cristy Mar 2 at 19:04
  • okay i think i follow... i do not see the expected result due to the timing of when the request is actually processed.. how would i be able to ensure that the global variable is set in time for when i need to leverage it in the other functions? – user2004758 Mar 2 at 19:33
  • my assumption is that i have to use a callback at some pt... [i did update to using rest w/ an ajax call that pointed to webproperties & that was much simpler.. thanks!] – user2004758 Mar 2 at 19:34

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.