Open wrharper-AASP opened 1 year ago
Thank you for contacting us! Any issue or feedback from you is quite important to us. We will do our best to fully respond to your issue as soon as possible. Sometimes additional investigations may be needed, we will usually get back to you within 2 days by adding comments to this issue. Please stay tuned.
Hi @wrharper-AASP, I have followed your repro step and got a same result. I tried a lot and found that when we trigger it in console, it regards the whole Teams as a page, so browser can find the button then click it. When we trigger it in code level, it will only focus on the elements in tab page itself, so there is no button in it, it will output click undefined.
Hi @wrharper-AASP, I have followed your repro step and got a same result. I tried a lot and found that when we trigger it in console, it regards the whole Teams as a page, so browser can find the button then click it. When we trigger it in code level, it will only focus on the elements in tab page itself, so there is no button in it, it will output click undefined.
That is correct, how can this be fixed?
I think in Teams, by design in a tab can not control the experience out of this tab.
I think in Teams, by design in a tab cannot control the experience out of this tab.
I can do navigation to the other tab within the current tab, but that causes new issues.
This is needed due to an error check on authorization so they can change a setting that is on another tab requiring the fix and go back.
in TeamsJsBlazorInterop.js i found:
export function navigateToTab(tabInstance) {
return microsoftTeams.pages.tabs.navigateToTab(tabInstance);
}
so I tried to call it:
Console.WriteLine(await JsRuntime.InvokeAsync<string>("navigateToTab", "index2"));
but get error: Microsoft.JSInterop.JSException: Could not find 'navigateToTab' ('navigateToTab' was undefined).
I tried creating a javascript that you would use normally:
function getQuery()
{
const querystring = window.location.search;
const urlParams = new URLSearchParams(queryString);
return urlParams.get('redirect');
}
you get an error saying querystring is empty even though i used a param: NavigationManager.NavigateTo("/tab3?redirect=tab1", true);
if you use top.location.search(which would work), you get this error: Blocked a frame with origin from accessing a cross-origin frame
Every way that would normally work isn't possible. How can this be done? The closest direction to the right answer I would think is TeamsFx blazor interop from the first error. This should be found, something is missing...
The first error I think you may try to add this function in \Interop\TeamsSDK\MicrosoftTeams.cs Then include it '@inject MicrosoftTeams MicrosoftTeams;' in Welcome.razor
I created:
public Task<string> NavigateToTab(string tabInstance)
{
return InvokeAsync<string>("navigateToTab", tabInstance);
}
Tried to use it:
Console.WriteLine(MicrosoftTeams.NavigateToTab("index2"));
Error:
Microsoft.JSInterop.JSException: The library has not yet been initialized
Interesting since I was able to call IsInTeams before this?
At this point you can easily see how crazy it is just to do something that should be very easy to do. This has been 5 or so different attempts to go around the problem and none of them work so far. It shouldn't be this complicated.
@wrharper-AASP The error message Microsoft.JSInterop.JSException: The library has not yet been initialized
indicated that you had not initialize Teams JS SDK before invoke navigateToTab function.
Following may work.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
await MicrosoftTeams.InitializeAsync();
await MicrosoftTeams.NavigateToTab(tabInstance);
}
}
You can find the TabInstance interface definition here.
While as far as I know, navigateToTab
only works for channel tab or group tab. If you want to navigate between personal tab, you may want to use microsoftTeams.pages.navigateToApp();
. Reference.
Here's an example: https://github.com/hund030/BlazorNavigateToTab/blob/main/MyTeamsApp5/wwwroot/js/TeamsJsBlazorInterop.js#L33 https://github.com/hund030/BlazorNavigateToTab/blob/main/MyTeamsApp5/Interop/TeamsSDK/MicrosoftTeams.cs#L38 https://github.com/hund030/BlazorNavigateToTab/blob/main/MyTeamsApp5/Pages/Tab.razor#LL22C50-L22C50
This looks like it may work. I'll test it when I get a chance, thanks.
EDIT: where does the app ID hide in the files?
I would expect microsoftTeams.app.id to exist but it doesn't appear to be possible to get this anywhere? It should be possible to get its own id? In the manifest it's "{{state.fx-resource-appstudio.teamsAppId}}", how can this be called outside of the manifest?
I fixed another problem. I noticed TeamsContext exists but it always comes back with a bunch of null info. Here is the correct way to capture it's info:
public class Context
{
public App app { get; set; }
public Page page { get; set; }
public User user { get; set; }
public Sharepointsite sharePointSite { get; set; }
public class App
{
public string locale { get; set; }
public string sessionId { get; set; }
public string theme { get; set; }
public int iconPositionVertical { get; set; }
public string parentMessageId { get; set; }
public long userClickTime { get; set; }
public string userFileOpenPreference { get; set; }
public Host host { get; set; }
public string appLaunchId { get; set; }
}
public class Host
{
public string name { get; set; }
public string clientType { get; set; }
public string sessionId { get; set; }
public string ringId { get; set; }
}
public class Page
{
public string id { get; set; }
public string frameContext { get; set; }
public string subPageId { get; set; }
public bool isFullScreen { get; set; }
public bool isMultiWindow { get; set; }
public string sourceOrigin { get; set; }
}
public class User
{
public string id { get; set; }
public string licenseType { get; set; }
public string loginHint { get; set; }
public string userPrincipalName { get; set; }
public Tenant tenant { get; set; }
}
public class Tenant
{
public string id { get; set; }
public string teamsSku { get; set; }
}
public class Sharepointsite
{
public string teamSiteUrl { get; set; }
public string teamSiteDomain { get; set; }
public string teamSitePath { get; set; }
public string mySitePath { get; set; }
public string mySiteDomain { get; set; }
}
}
is there a reason why this wouldn't work? this should bypass the appid problem:
export function navigateToPage(pageId) {
microsoftTeams.pages.currentApp.navigateTo(pageId)
}
However, when i integrate and run it, no errors happen and nothing changes.
The reason why navigateToApp won't work is because the published id is also different than the local. so, it's not a good way to handle it and it can change with custom publishes as well. there needs to be a way to automatically get the appid from within the app.
where does the app ID hide in the files?
You can find the TeamsAppId from .fx/states/state.{envName}.json
. state.local.json
is for local and by default state.dev.json
is for published, if you are using Teams Toolkit to provision the remote resources.
You can set the value to your environment variables and reference it from your code. I think .NET supports multiple environments by appsettings.json file. You can set your local TeamsAppId in appsettings.Development.json and set published TeasmAppId in your Azure App Service's appsettings.
Here's an example of using Teams Toolkit to automatically update Azure App Service's appsettings:
Update .fx/configs/azure.parameter.dev.json
as following:
"parameters": {
"provisionParameters": {
"value": {
...
"teamsAppId": "{{state.fx-resource-appstudio.teamsAppId}}"
}
}
}
Update bicep files:
@secure()
param provisionParameters object // Teams Toolkit pass the provisionParameters from `azure.parameter.dev.json` to Bicep engine.
var teamsAppId= provisionParameters['teamsAppId'] //
// You can find the webApp resources in your bicep file, add teamsAppId into its appSettings
resource webApp 'Microsoft.Web/sites@2021-02-01' = {
kind: 'app'
location: resourceGroup().location
name: webAppName
properties: {
serverFarmId: serverfarm.id
siteConfig: {
appSettings: [
.......
{
name: 'TEAMS_APP_ID'
value: teamsAppId
}
]
}
}
}
After that, re-run the provision command to apply the bicep changes.
is there a reason why this(navigateToPage) wouldn't work?
According to the document microsoft-teams-js-pages-tabs-navigatetotab, navigateToPage accept a tabInstance object. I didn't try but I assume you may want to write code like:
microsoftTeams.app.initialize();
var pageInfo = microsoftTeams.pages.tabs.getTabInstances(); // get tab instance of current channel or group.
microsoftTeams.pages.tabs.navigateToTab(pageInfo.teamTabs[1]);
To invoke these functions in Blazor, you may need to create a PageInfomation class and a TabInstance class for type annotation. Just as you have done for Context class.
for some reason, getTabInstances comes back empty.
What if i publish to the store? would it then be another id? this seems like the wrong direction to go.
According to the docs, currentApp should exist and this would be the right path to do this: https://learn.microsoft.com/en-us/javascript/api/@microsoft/teams-js/pages.currentapp?view=msteams-client-js-latest Can we get this fixed instead of trying to find ways around it?
So far, all attempts don't work or end up creating a chain of events of more problems.
The 2 possible solutions to get this fixed: 1, fix getTabInstances so it returns what it should per docs.
These features need to be fixed because it really puts limits on possibilities for everyone.
any update on currentApp and getTabInstances objects not working? We need a proper fix instead of this:
@wrharper-AASP Sorry for delay response.
Describe the bug Normally, you can simulate clicks in javascript, but this does not appear to be possible in Blazor/TeamsFx.
To Reproduce Go to any Teams app with a browser and do F12 dev tools. Go to the console and type: document.getElementsByClassName('btn')[1].click(); This will click the 2nd tab.
If you try to do this same thing in the TeamsFx toolkit Blazor via a Javascript call you get the error: TypeError: Cannot read properties of undefined (reading 'click')
Javascript in _Host.cshtml:
Call anywhere in the program:
Screenshots
Visual Studio 2022 TeamsFx 2.0