Add IUriHelper.NavigateTo

This commit is contained in:
Steve Sanderson 2018-03-16 11:19:09 +00:00
parent cb473e8ad7
commit d0731c337d
5 changed files with 52 additions and 5 deletions

View File

@ -1,6 +1,6 @@
import { registerFunction } from '../Interop/RegisteredFunction'; import { registerFunction } from '../Interop/RegisteredFunction';
import { platform } from '../Environment'; import { platform } from '../Environment';
import { MethodHandle } from '../Platform/Platform'; import { MethodHandle, System_String } from '../Platform/Platform';
const registeredFunctionPrefix = 'Microsoft.AspNetCore.Blazor.Browser.Services.BrowserUriHelper'; const registeredFunctionPrefix = 'Microsoft.AspNetCore.Blazor.Browser.Services.BrowserUriHelper';
let notifyLocationChangedMethod: MethodHandle; let notifyLocationChangedMethod: MethodHandle;
let hasRegisteredEventListeners = false; let hasRegisteredEventListeners = false;
@ -24,8 +24,7 @@ registerFunction(`${registeredFunctionPrefix}.enableNavigationInteception`, () =
const href = anchorTarget.getAttribute('href'); const href = anchorTarget.getAttribute('href');
if (isWithinBaseUriSpace(toAbsoluteUri(href))) { if (isWithinBaseUriSpace(toAbsoluteUri(href))) {
event.preventDefault(); event.preventDefault();
history.pushState(null, /* ignored title */ '', href); performInternalNavigation(href);
handleInternalNavigation();
} }
} }
}); });
@ -33,6 +32,20 @@ registerFunction(`${registeredFunctionPrefix}.enableNavigationInteception`, () =
window.addEventListener('popstate', handleInternalNavigation); window.addEventListener('popstate', handleInternalNavigation);
}); });
registerFunction(`${registeredFunctionPrefix}.navigateTo`, (uriDotNetString: System_String) => {
const href = platform.toJavaScriptString(uriDotNetString);
if (isWithinBaseUriSpace(toAbsoluteUri(href))) {
performInternalNavigation(href);
} else {
location.href = href;
}
});
function performInternalNavigation(href: string) {
history.pushState(null, /* ignored title */ '', href);
handleInternalNavigation();
}
function handleInternalNavigation() { function handleInternalNavigation() {
if (!notifyLocationChangedMethod) { if (!notifyLocationChangedMethod) {
notifyLocationChangedMethod = platform.findMethod( notifyLocationChangedMethod = platform.findMethod(

View File

@ -104,6 +104,17 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Services
throw new ArgumentException($"The URI '{absoluteUri}' is not contained by the base URI '{baseUriPrefix}'."); throw new ArgumentException($"The URI '{absoluteUri}' is not contained by the base URI '{baseUriPrefix}'.");
} }
/// <inheritdoc />
public void NavigateTo(string uri)
{
if (uri == null)
{
throw new ArgumentNullException(nameof(uri));
}
RegisteredFunction.InvokeUnmarshalled<object>($"{_functionPrefix}.navigateTo", uri);
}
private static void EnsureBaseUriPopulated() private static void EnsureBaseUriPopulated()
{ {
// The <base href> is fixed for the lifetime of the page, so just cache it // The <base href> is fixed for the lifetime of the page, so just cache it

View File

@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Blazor.Services
/// <summary> /// <summary>
/// Gets the current absolute URI. /// Gets the current absolute URI.
/// </summary> /// </summary>
/// <returns>The browser's current absolute URI.</returns> /// <returns>The current absolute URI.</returns>
string GetAbsoluteUri(); string GetAbsoluteUri();
/// <summary> /// <summary>
@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Blazor.Services
/// <param name="absoluteUri">An absolute URI that is within the space of the base URI prefix.</param> /// <param name="absoluteUri">An absolute URI that is within the space of the base URI prefix.</param>
/// <returns>A relative URI path.</returns> /// <returns>A relative URI path.</returns>
string ToBaseRelativePath(string baseUriPrefix, string locationAbsolute); string ToBaseRelativePath(string baseUriPrefix, string locationAbsolute);
/// <summary>
/// Navigates to the specified URI.
/// </summary>
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
/// prefix (as returned by <see cref="GetBaseUriPrefix"/>).</param>
void NavigateTo(string uri);
} }
} }

View File

@ -110,6 +110,16 @@ namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests
Assert.Equal("This is the default page.", app.FindElement(By.Id("test-info")).Text); Assert.Equal("This is the default page.", app.FindElement(By.Id("test-info")).Text);
} }
[Fact]
public void CanNavigateProgrammatically()
{
SetUrlViaPushState($"{ServerPathBase}/RouterTest/");
var app = MountTestComponent<TestRouter>();
app.FindElement(By.TagName("button")).Click();
Assert.Equal("This is another page.", app.FindElement(By.Id("test-info")).Text);
}
public void Dispose() public void Dispose()
{ {
// Clear any existing state // Clear any existing state

View File

@ -1,4 +1,6 @@
<ul> @inject Microsoft.AspNetCore.Blazor.Services.IUriHelper uriHelper
<ul>
<li><a href="/subdir/RouterTest/">Default</a></li> <li><a href="/subdir/RouterTest/">Default</a></li>
<li><a href="/subdir/RouterTest/?abc=123">Default with query</a></li> <li><a href="/subdir/RouterTest/?abc=123">Default with query</a></li>
<li><a href="/subdir/RouterTest/#blah">Default with hash</a></li> <li><a href="/subdir/RouterTest/#blah">Default with hash</a></li>
@ -7,3 +9,7 @@
<li><a href="/subdir/RouterTest/Other?abc=123">Other with query</a></li> <li><a href="/subdir/RouterTest/Other?abc=123">Other with query</a></li>
<li><a href="/subdir/RouterTest/Other#blah">Other with hash</a></li> <li><a href="/subdir/RouterTest/Other#blah">Other with hash</a></li>
</ul> </ul>
<button onclick=@{ uriHelper.NavigateTo("RouterTest/Other"); }>
Programmatic navigation
</button>