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

Ribbon button requires 2 clicks before function is invoked #2744

Closed
questicles opened this issue Aug 2, 2022 · 15 comments
Closed

Ribbon button requires 2 clicks before function is invoked #2744

questicles opened this issue Aug 2, 2022 · 15 comments
Assignees
Labels
Needs: attention 👋 Waiting on Microsoft to provide feedback

Comments

@questicles
Copy link

questicles commented Aug 2, 2022

Message from office-js bot:
We’re closing this issue because it has been inactive for a long time. We’re doing this to keep the issues list manageable and useful for everyone. If this issue is still relevant for you, please create a new issue.
Thank you for your understanding and continued feedback.

Provide required information needed to triage your issue

Reporting behaviour logged here 2 years ago but was closed due to author inactivity in the hopes I can get some direction now in 2022: #1029

Your Environment

  • Platform: Office on the web
  • Host: Excel
  • Office version number: Office 365 (latest)
  • Operating System: Windows 10
  • Browser (if using Office on the web): Chrome (latest)

Expected behavior

The first time a ribbon button is clicked after an add-in is added to Excel or the page is reloaded, the function should be invoked, even if the static assets have to be downloaded first. It should not require a second click to invoke the function.

Current behavior

The first click on a ribbon button after the add-in is added or the page is refreshed, is only triggering the downloading of the add-in static assets but does not invoke the function named in the manifest. A secondary click is required to invoke the function, because the static assets are now cached. While the static assets do not need to be downloaded, a single click always invokes the function.

Steps to reproduce

  1. Create a new add-in and configure to use a SharedRuntime as per the official documentation
  2. Create 1 ribbon button that is an "ExecuteFunction" action to call a global function that does anything, such as console.log.
  3. Add the add-in to Excel (or reload the browser to repeat testing)
  4. Click on the ribbon button - note function is not invoked

Link to live example(s)

n/a

Provide additional details

n/a

Context

This will be a stop ship experience for our new product. We need the shared runtime to connect ribbon button clicks to our SPA app state running inside the task pane. Requiring a user to click the ribbon button twice seems like an oversight but would like some guidance.

Useful logs

n/a

@ghost ghost added the Needs: triage 🔍 New issue, needs PM on rotation to triage ASAP label Aug 2, 2022
@JinghuiMS JinghuiMS added Needs: attention 👋 Waiting on Microsoft to provide feedback and removed Needs: triage 🔍 New issue, needs PM on rotation to triage ASAP labels Aug 2, 2022
@aluke1
Copy link

aluke1 commented Aug 31, 2022

I am having the exact same issue. In my case, the ribbon button is supposed to invoke a function that opens the taskpane. However, when the user first installs the Add-In from the store, the first click of the ribbon button does not invoke the function, so the taskpane does not appear.

This is very frustrating for users because the Add-In doesn't appear to have installed properly since nothing happens when the click the ribbon. So their first experience with the Add-In is that it doesn't work as expected.

Is there a known work-around to prevent this from occurring?

@JiayuanL
Copy link

JiayuanL commented Sep 1, 2022

Thanks for reaching! We tried the scenario but cannot reproduce it in our side, would you please share the manifest also shared runtime home page you are using? We could try investigating based on those, thanks!

@aluke1
Copy link

aluke1 commented Sep 1, 2022

Hi @JiayuanL, sure I can share all of that. First of all, you can experience the issue if you load our AddIn through the store since it is available in production. Here are instructions for finding us in the store, under "installing the AddIn":
https://www.valueanalytics.org/excel

Here is the dev manifest file (only difference from prod are the URLs)
manifest.development.xml.txt

Here is the shared runtime .html file (after running webpack):
taskpane.html.txt

And just for completeness, here is the taskpane.js file where we register the functions:
taskpane.js.txt

The taskpane.js file is the pre-webpack version since it is difficult to follow after bundling. Please let me know if you need anymore information!

Thanks,
Adam

@JiayuanL
Copy link

JiayuanL commented Sep 1, 2022

Thanks for your reply @aluke1, I could access your Addin from store. I could trigger the taskpane to show by clicking "login" ribbon button only one time, I'd like to check is "login" button what you mentioned need two time click? Is that intermittently repro or consistent?

@aluke1
Copy link

aluke1 commented Sep 1, 2022

Hi @JiayuanL, yes it is the login button that should show the taskpane. It consistently requires two clicks for myself and others. Here is a screenshot of my excel version:
excel_version

@madhavagrawal17
Copy link

@aluke1, I tried to debug this issue and it seems like some race condition on the first click when the first time the runtime is created. Can you please provide me the implementation snippet inside method "app.loadPage(event, app.pages.loginPage)"? It seems we are invoking the action "login_action" but the Task pane is not launching for the first time. I want to see if you have any conditions before you call "Office.addin.showAsTaskpane()" on the JS side.

@aluke1
Copy link

aluke1 commented Sep 6, 2022

hi @madhavagrawal17, yes there are several other methods that are called before showAsTaskpane() is invoked. Here is loadPage:

async loadPage(event, page) {
        try {
            await this.clear_styling()
            this.set_current_nav(page.nav_id)
            await Office.addin.showAsTaskpane();
            await this._pageManager.setCurrentPage(page);
        } catch (error) {
            //console.log(error)
        } finally {
            if (event.completed instanceof Function){
                event.completed()
            }
          }
    };

here is clear_styling:

private async clear_styling() {
       let styled_cells = await this._runtimeStorage.getStyled()
       // this block clears the styling applied by the builder
       if (styled_cells) {
           let styled_obj = JSON.parse(styled_cells)
           if (styled_obj) {
               await Excel.run(async (context) => {
                   let worksheet = context.workbook.worksheets.getItem(styled_obj['sheet'])
                   styled_obj['cells'].forEach((cell) => {
                       let range = worksheet.getRange(cell)
                       range.format.fill.clear()
                   })
                   await context.sync()
               })
               await this._runtimeStorage.setStyled(null)
           }
       }
       // this will clear the selected input option
       this._formulaBuilderPage.clearSelectedInput()
   };

here is this._runtimeStorage.getStyled():

    getStyled(): Promise<string> {
        return this.getItem(this._styledKey)
    }
    
    private getItem(key: string): Promise<string> {
        return this._officeRuntimeStorage.getItem(key);
    }

here is set_current_nav:

    private set_current_nav(nav_id) {
        $(".nav-button").removeClass("active")
        $(nav_id).addClass("active")
    }

@aluke1
Copy link

aluke1 commented Sep 6, 2022

@madhavagrawal17 there are other parts of the app that style some of the sheet cells, and we clear the styling when the user navigates between pages. The cells we have styled are stored in the OfficeRuntime.Storage object so we can access them later.

@madhavagrawal17
Copy link

@aluke1, I tried to check if I am getting the call for the showAsTaskpane() for the first click and it seems I am not getting the call. Can you locally check if there is a failure in the clear_styling() method? You could also try locally moving the showAsTaskpane() at the top of the loadPage() method to see if the first click is working in order for us to narrow down the root cause.

@aluke1
Copy link

aluke1 commented Sep 7, 2022

@madhavagrawal17, I refactored the loadPage() method for testing and removed all of the other function calls:

async loadPage(event, page) { await Office.addin.showAsTaskpane(); event.completed(); }

However, it still requires two clicks for the taskpane to open upon initial load. So, it appears there is an issue with the showAsTaskpane() method.

I am developing on mac and I cannot see any of the logs until I can open the web inspector, which requires the taskpane to be open. So unfortunately, I can't log anything prior to the taskpane being open.

@madhavagrawal17
Copy link

@aluke1, Thanks for providing the information. I am looking into this issue.

@madhavagrawal17
Copy link

@aluke1, I appreciate your patience. I think I am able to figure out the race condition. The problem is the API is being called before "Office.onReady()". What you can try is putting all the API call inside the "load_page" method inside the "Office.onReady()" so that it will be called when the Office.js is loaded and ready. Please let me know if this solves your problem.

@aluke1
Copy link

aluke1 commented Sep 9, 2022

@madhavagrawal17, thank you for your suggestion. I refactored the js to nest the load_page function in the Office.onReady() function:

async function login_action(event) { Office.onReady(function(info) { app.loadPage(event, app.pages.loginPage); }) }

However, I still needed to click twice to load the taskpane initially. However, I did find another solution for this problem.

I noticed that the taskpane.js script was loading using the defer keyword in the .html file:
<script defer src="polyfill.js"></script><script defer src="taskpane.js"></script></head>
The defer keyword was added by the webpack builder. After re-configuring the webpack config to use blocking loading, like this:
new HtmlWebpackPlugin({ filename: "taskpane.html", template: "./src/taskpane/taskpane.html", chunks: ["polyfill", "taskpane"], scriptLoading: "blocking" })
The js files are now loaded in the .html body and the defer keyword is no longer included. The taskpane opens on first click as expected now.

It appears that blocking loading is required for the js to load properly upon installation. You guys should definitely update your documentation/yeoman projects to include this, since the default webpack config that we get by running:
yo office --projectType taskpane --name "my office add in" --host excel --js true
as recommended here will used the deferred loading option by default.

@HarryPi
Copy link

HarryPi commented May 19, 2023

We are facing the same issue, even though the dialog is on the .then function of office.onReady ..........
The only way this will work on the first click is if you first open a taskpane from your ribbon, then that will consistently works on first click until you close your office application in our case Excel

Have confirmed a similar fix for anyone struggling, with @aluke1, i was using Angular 15, the issue was main.ts that included the function scripts was having a race condition with Office.js, as soon as i moved the functions in a different .js file and included that in my project.json scripts it worked with one click

@gergzk gergzk closed this as not planned Won't fix, can't repro, duplicate, stale Apr 18, 2024
@iambacon
Copy link

iambacon commented Sep 27, 2024

Thanks for sharing this solution @aluke1 ! I also had the same issue with an Excel add-in built using React, and changing the scriptLoading to "blocking" in the Webpack config worked perfectly for me. The taskpane now opens on the first click as expected.

This really should be properly documented, especially in the default Yeoman project setup, as the deferred script loading can cause issues like this. It would save a lot of time for other developers facing the same problem. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: attention 👋 Waiting on Microsoft to provide feedback
Projects
None yet
Development

No branches or pull requests

8 participants