Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPFX Application Extension - used for adding custom javascript for modern page but it fails #1674

Closed
harshdamaniahd opened this issue Apr 17, 2018 · 15 comments
Labels
area:spfx Category: SharePoint Framework (not extensions related) status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed) type:question Question... if answered, will be tagged as such.

Comments

@harshdamaniahd
Copy link

I have created a custom script which fetches some user profile information and some information from termstore.The script is working fine.
Now when I deploy this script using extension to add it to page it also gets added.
But the problem is that the script executes before webparts are loaded
The script returns userprofile info as global object.Based on this my webparts need to load ,but the script executes after webparts are loaded ?
Is this the normal behavior ?

@VesaJuvonen VesaJuvonen added type:question Question... if answered, will be tagged as such. area:spfx Category: SharePoint Framework (not extensions related) status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed) labels Apr 17, 2018
@StfBauer
Copy link
Collaborator

Have you registered your extension as a header extension or as a footer extension?

@harshdamaniahd
Copy link
Author

harshdamaniahd commented Apr 18, 2018 via email

@harshdamaniahd
Copy link
Author

I am using this code. ALSO my js code contains JSOM to fetch taxonomy
export default class CobGlobalJsApplicationCustomizer
extends BaseApplicationCustomizer {

private _externalJsUrl: string = "https://sharepointnutsandbolts.azurewebsites.net/scripts/SPFxGlobalScript.js";

@OverRide
public onInit(): Promise {
console.log(CobGlobalJsApplicationCustomizer.onInit(): Entered.);

let scriptTag: HTMLScriptElement = document.createElement("script");
scriptTag.src = this._externalJsUrl;
scriptTag.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(scriptTag);

console.log(`CobGlobalJsApplicationCustomizer.onInit(): Added script link.`);
console.log(`CobGlobalJsApplicationCustomizer.onInit(): Leaving.`);
return Promise.resolve<void>();

}

// other methods omitted..
}

@NavaneethaDev
Copy link

any help on this issue? I am also facing this issue. Thanks

@waldekmastykarz
Copy link
Collaborator

Yes, that's the default behavior. At this moment, there is no way for you to determine when the page and all of its components (extensions and web parts) have been loaded.

What you're trying to achieve is to build a service that offers shared data to the different components on the page. This isn't possible to do reliably at this moment as it would require the support for libraries which have been requested a while ago already: https://sharepoint.uservoice.com/forums/329220-sharepoint-dev-platform/suggestions/19224202-add-support-for-library-packages-in-the-sharepoint.

@NavaneethaDev
Copy link

Yes exactly, the problem which i am facing is, the java script is loaded before the page is loads. so it's unable to find the DOM elements. In my page, we have spfx web parts and OOTB web parts like events, my documents and we wanted to change some text to arrow image using javascript. This is not happening. Some time its working and some times its not.

We almost tried all the options but we are unable to achieve this.
methods we tried

  1. Used extension to add the Js files
  2. Used script editor web part and referenced the Js files
  3. Placed the java script directly into the script editor

None of these works. but our customer is more interested in this. @waldekmastykarz, Could you please suggest any other alternatives or approaches to implement this?

@harshdamaniahd
Copy link
Author

So you can do one thing you can create global object or session object and wait for the value in object.
Like when all you webparts are loaded you can set value in session object.
Once done then you can execute the js
you can use setTimeout function and promises

@NavaneethaDev
Copy link

If i use setTimeout, it is not working properly. few times its working, few times not. can you please how to achieve the below from your comment?

"you can do one thing you can create global object or session object and wait for the value in object.
Like when all you web parts are loaded you can set value in session object."l

@harshdamaniahd
Copy link
Author

harshdamaniahd commented Apr 25, 2018

My assumption is that you are trying to change something in OOB webpart,
This is a typescript function

export function waitForUserInfo(): Promise<{}> {
return new Promise((resolve, reject)=> {
(function wait() {
if (document.getElementById("") !== null) { // the id of element which you are trying to change.

    return resolve(); //or do something
  } else {
    console.log("waiting for id to be obtained");
  }
  setTimeout(wait, 30);
})();

});
}

Let me know if this helps

@waldekmastykarz
Copy link
Collaborator

As I mentioned, there is no reliable way of implementing this at this moment. You can use workarounds, like timeout to wait for the page to load, but that is likely to fail, for example when user navigates to another page, which isn't causing a full page reload.

While I understand what you're being asked for, I would strongly discourage you from implementing it as it's only a matter of time until it will cause problems.

@lexschulz
Copy link

lexschulz commented Jun 4, 2018

In my case I used setInterval to check if the element is there. Not beautiful but it works:

    const interval = window.setInterval(() => {
       //Some code
       if (value.length > 0) {   
          //Some code
          window.clearInterval(interval);       
      }
    }, 300);

@harshdamaniahd
Copy link
Author

Yes..I have this solution in mind

@mariuszwojtkowski
Copy link

This is not the first post I have read while looking for a reliable way to detect if the page has finished loading completely. Microsoft broke jQuery's document.ready and also the DOMContentLoaded event.
We are forced to use setInterval.

@patmill
Copy link
Contributor

patmill commented Sep 25, 2021

Sorry - cleaning up old bugs. There really isn't a way to determine when webparts have finished loading, etc. particularly as they can load as the page is scrolled, etc. Additionally, due to the nature of js promises / script loading / etc. there is no way to say that component A will finish loading before component B (unless there is a dependency on a library). However, if the desire is to have singleton code that can be executed / shared across all your webparts, then the library feature / component is the way to go. Documentation is here - https://docs.microsoft.com/en-us/sharepoint/dev/spfx/library-component-overview with a tutorial here - https://docs.microsoft.com/en-us/sharepoint/dev/spfx/library-component-tutorial

@patmill patmill closed this as completed Sep 25, 2021
@ghost
Copy link

ghost commented Oct 2, 2021

Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues

@SharePoint SharePoint locked as resolved and limited conversation to collaborators Oct 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area:spfx Category: SharePoint Framework (not extensions related) status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed) type:question Question... if answered, will be tagged as such.
Projects
None yet
Development

No branches or pull requests

8 participants