The Url of dialog box does not work with angular.b

2019-06-18 16:40发布

问题:

I have a mean-stack website. I want to use ExecuteFunction to bind a button to launch this website in a Dialog box:

function doSomethingAndShowDialog(event) {
    clickEvent = event;
    Office.context.ui.displayDialogAsync("https://localhost:3000/try", {}, function () {})
}

Clicking on the button opens a dialog box with the following url, it does show the content of the page:

https://localhost:3000/try?_host_Info=excel|web|16.00|en-us|7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc|isDialog#%2Ftry%3F_host_Info=excel%7Cweb%7C16.00%7Cen-us%7C7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc%7CisDialog

However, in the console, there are Error: $rootScope:infdig Infinite $digest Loop at angular.bootstrap(document, ['myapp']):

var wait = setTimeout(myFunction, 1000);
Office.initialize = function (reason) {
    $(document).ready(function () {
        angular.bootstrap(document, ['myapp']) 
        console.log("bootstrapped inside Office.initialize");
        clearTimeout(wait);
    })
}

function myFunction () {
    $(document).ready(function () {
        angular.bootstrap(document, ['myapp']) 
        console.log("bootstrapped outside Office.initialize");
    })
}

app = angular.module("myapp", []);
app.config(...);
app.controller(...);

If we just open https://localhost:3000/try in a browser, there is no error.

Does anyone know why that long url did not work with angular.bootstrap? How could we fix this?

Edit 1: a screenshot of the console for https://localhost:3000/try?_host_Info=excel.... Note that neither bootstrapped inside Office.initialize nor bootstrapped outside Office.initialize is displayed. But If I run https://localhost:3000/try in a browser, I will only see bootstrapped outside Office.initialize, when I call it from an Excel client, I will only see bootstrapped inside Office.initialize.

回答1:

It sounds like you're trying to wire up a page that can operate as either an add-in or a stand-alone page. Whenever possible it is best to maintain separate views for each use case. If nothing else, it makes everything a lot more straight forward. Combining them is likely creating far more overhead and headache that it's worth.

Part of your issue here is that you've got two separate code paths and you're assuming only one path will execute at a time. When loaded in a browser this is true, it will simply ignore the Office.initialize function. When loaded within Office however it will execute both paths. One will be executed by Office, the other will be executed by setTimeOut after 1 second.

If you have two distinct code paths where only one is ever executed, you need to test to determine if you're operating as an add-in or as a standalone page. This is where those query parameters come into play. If you have a _host_Info query parameter defined then you're operating within Office. For example:

if (getParameterByName('_hostInfo')) { // _hostInfo is defined
    Office.initialize = function (reason) {
        $(document).ready(function () {
            angular.bootstrap(document, ['myapp'])
            console.log("bootstrapped inside Office.initialize");
        });
    }
} 
else { // _hostInfo is not defined
    $(document).ready(function () {
        angular.bootstrap(document, ['myapp'])
        console.log("bootstrapped outside Office.initialize");
    })
}

Note that getParameterByName() here is a function pulled from this answer. You could use any method you prefer however.