Skip to content

Commit 1dd2573

Browse files
committed
Permalink service updates added event for perma value detection and update link.
1 parent 3f45335 commit 1dd2573

File tree

8 files changed

+210
-9
lines changed

8 files changed

+210
-9
lines changed

.github/docs/PermaLink.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ For more details see Usage section.
3232
### Functions
3333
- **`WatchPermaLinks()`**: **`void WatchPermaLinks()`** <br />
3434
Starts a navigation watcher which will check for Permalinks in the URLs.
35+
- **`ChangePermalink()`**: **`void ChangePermalink(string? newPermalink, bool doNotNavigate)`** <br />
36+
Modify the current URL with given new peralink value and trigger navigation or just update browser History.
3537
- **`Dispose()`: `@implements IDisposable` interface** <br />
3638
Component implements `IDisposable` interface Blazor framework will call it when parent removed from render tree.
3739

40+
### Events
41+
- **`PermalinkDetected`: `event EventHandler<PermalinkDetectedEventArgs>** <br />
42+
Event handler for parmalinks detected on navigation.
43+
3844
## `PermaLinkElement` component
3945

4046
### Properties
@@ -68,9 +74,17 @@ Callback function called when Permalink icon clicked and **`PermaLinkIconActions
6874
## PermaLinkBlazorServerInitializer
6975
Available from v1.4.0 It is convenient wrapper component to initialize navigation watcher in your Blazor Server App `MainLayout.razor` page. **Only one Initializer component allowed per Application.**
7076

77+
### Properties
78+
- **`SmootScroll`: `bool { get; set; }` (default: false)** <br />
79+
Scroll should be jump or smoothly scroll. **Note: smooth scroll on element level might not supported by all browsers.**
80+
7181
## PermalinkBlazorWasmInitializer
7282
Available from v1.4.0 It is convenient wrapper component to initialize navigation watcher in your Blazor WebAssembly App `MainLayout.razor` page. **Only one Initializer component allowed per Application.**
7383

84+
### Properties
85+
- **`SmootScroll`: `bool { get; set; }` (default: false)** <br />
86+
Scroll should be jump or smoothly scroll. **Note: smooth scroll on element level might not supported by all browsers.**
87+
7488
# Configuration
7589

7690
## Installation
@@ -141,7 +155,7 @@ Also instance should be disposed.
141155
```
142156
@*Permalink initialize*@
143157
@using Majorsoft.Blazor.Components.PermaLink
144-
<PermalinkBlazorWasmInitializer />
158+
<PermalinkBlazorWasmInitializer SmoothScroll="false" />
145159
```
146160

147161
#### Server hosted projects
@@ -208,7 +222,7 @@ It has to be instantiated manually by using the following code. Also instance sh
208222
```
209223
@*Permalink initialize*@
210224
@using Majorsoft.Blazor.Components.PermaLink
211-
<PermaLinkBlazorServerInitializer />
225+
<PermaLinkBlazorServerInitializer SmoothScroll="false" />
212226
```
213227

214228
#### Creating permalink (#) navigation points inside a Blazor page

src/Majorsoft.Blazor.Components.PermaLink/IPermaLinkWatcherService.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ namespace Majorsoft.Blazor.Components.PermaLink
88
/// </summary>
99
public interface IPermaLinkWatcherService : IDisposable
1010
{
11+
/// <summary>
12+
/// Should scroll smoothly to the found permalink element or jump.
13+
/// Note: smooth scroll on element level might not supported by all Browsers.
14+
/// </summary>
15+
bool SmoothScroll { get; set; }
16+
17+
/// <summary>
18+
/// Event handler for parmalinks detected on navigation.
19+
/// </summary>
20+
public event EventHandler<PermalinkDetectedEventArgs> PermalinkDetected;
21+
22+
/// <summary>
23+
/// Modify the current URL with given new peralink value and trigger navigation or just update browser History.
24+
/// </summary>
25+
/// <param name="newPermalink">New peramlink value, NULL will remove permalink part from URL</param>
26+
/// <param name="doNotNavigate">False, will trigger a navigation. When true, just add new URL to the History</param>
27+
void ChangePermalink(string? newPermalink, bool doNotNavigate);
28+
1129
/// <summary>
1230
/// Starts a navigation watcher which will check for Permalinks in the URLs.
1331
/// </summary>

src/Majorsoft.Blazor.Components.PermaLink/Majorsoft.Blazor.Components.PermaLink.xml

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Majorsoft.Blazor.Components.PermaLink/PermaLinkBlazorServerInitializer.razor

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@
3131
}
3232
}
3333

34+
/// <summary>
35+
/// Gets or sets if peramlink should be scrolled smoothly into view or not.
36+
/// Note: smooth scroll on element level might not supported by all Browsers.
37+
/// </summary>
38+
[Parameter] public bool SmoothScroll
39+
{
40+
get => _permalinkWatcher.SmoothScroll;
41+
set { _permalinkWatcher.SmoothScroll = value; }
42+
}
43+
3444
public async ValueTask DisposeAsync()
3545
{
3646
if (_scrollHandler is not null)

src/Majorsoft.Blazor.Components.PermaLink/PermaLinkWatcherService.cs

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Text.RegularExpressions;
1+
using System;
2+
using System.Text.RegularExpressions;
23

34
using Majorsoft.Blazor.Components.Common.JsInterop.Scroll;
45

@@ -19,11 +20,17 @@ public class PermaLinkWatcherService : IPermaLinkWatcherService
1920
private readonly NavigationManager _navigationManager;
2021
private readonly ILogger<IPermaLinkWatcherService> _logger;
2122

22-
public PermaLinkWatcherService(IScrollHandler scrollHandler, NavigationManager navigationManager, ILogger<IPermaLinkWatcherService> logger)
23+
public event EventHandler<PermalinkDetectedEventArgs> PermalinkDetected;
24+
25+
public bool SmoothScroll { get; set; }
26+
27+
public PermaLinkWatcherService(IScrollHandler scrollHandler, NavigationManager navigationManager, ILogger<IPermaLinkWatcherService> logger, bool smoothScroll = false)
2328
{
2429
_scrollHandler = scrollHandler;
2530
_navigationManager = navigationManager;
2631
_logger = logger;
32+
33+
SmoothScroll = smoothScroll;
2734
}
2835

2936
public void WatchPermaLinks()
@@ -39,14 +46,67 @@ public void WatchPermaLinks()
3946
private void HandleLocationChanged(object sender, LocationChangedEventArgs e)
4047
{
4148
_logger.LogDebug($"{nameof(PermaLinkWatcherService)} - {nameof(HandleLocationChanged)}: navigation happened new URL: {e.Location}");
42-
var match = _poundRegex.Match(e.Location);
49+
var perma = DetectPermalink(e.Location);
4350

44-
if(match.Success && match.Groups.Count == 2)
51+
if(!string.IsNullOrWhiteSpace(perma))
4552
{
46-
var perma = match.Groups[1].Value;
4753
_logger.LogDebug($"{nameof(PermaLinkWatcherService)} - {nameof(HandleLocationChanged)}: PermaLink found: {perma}");
48-
_scrollHandler.ScrollToElementByNameAsync(perma);
54+
55+
if(PermalinkDetected is not null)
56+
{
57+
PermalinkDetected.Invoke(this, new PermalinkDetectedEventArgs(e, perma));
58+
}
59+
60+
_scrollHandler.ScrollToElementByNameAsync(perma, SmoothScroll);
61+
}
62+
}
63+
64+
public void ChangePermalink(string? newPermalink, bool doNotNavigate)
65+
{
66+
var perma = DetectPermalink(_navigationManager.Uri);
67+
if (!string.IsNullOrWhiteSpace(perma))
68+
{
69+
if (newPermalink?.ToLower() == perma?.ToLower()) //same
70+
{
71+
return;
72+
}
73+
74+
var newUri = _navigationManager.Uri.Replace($"#{perma}", "");
75+
if (string.IsNullOrWhiteSpace(newPermalink)) //remove
76+
{
77+
_navigationManager.NavigateTo(newUri);
78+
return;
79+
}
80+
81+
SetBrowserUrl($"{newUri}#{newPermalink}", doNotNavigate);
82+
}
83+
else
84+
{
85+
SetBrowserUrl($"{_navigationManager.Uri}#{newPermalink}", doNotNavigate);
86+
}
87+
}
88+
89+
private void SetBrowserUrl(string uri, bool doNotNavigate)
90+
{
91+
if(doNotNavigate)
92+
{
93+
//TODO: history.pushState(null, '', url);
94+
return;
95+
}
96+
97+
_navigationManager.NavigateTo(uri, false);
98+
}
99+
100+
private string DetectPermalink(string uri)
101+
{
102+
var match = _poundRegex.Match(uri);
103+
if (match.Success && match.Groups.Count == 2)
104+
{
105+
var perma = match.Groups[1].Value;
106+
return perma;
49107
}
108+
109+
return null;
50110
}
51111

52112
public void Dispose()

src/Majorsoft.Blazor.Components.PermaLink/PermalinkBlazorWasmInitializer.razor

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717
_permalinkWatcher.WatchPermaLinks();
1818
}
1919

20+
/// <summary>
21+
/// Gets or sets if peramlink should be scrolled smoothly into view or not.
22+
/// Note: smooth scroll on element level might not supported by all Browsers.
23+
/// </summary>
24+
[Parameter]
25+
public bool SmoothScroll
26+
{
27+
get => _permalinkWatcher.SmoothScroll;
28+
set { _permalinkWatcher.SmoothScroll = value; }
29+
}
30+
2031
public void Dispose()
2132
{
2233
_permalinkWatcher?.Dispose();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
3+
using Microsoft.AspNetCore.Components.Routing;
4+
5+
namespace Majorsoft.Blazor.Components.PermaLink
6+
{
7+
/// <summary>
8+
/// Event arguments for <see cref="PermaLinkWatcherService"/> PermalinkDetected event.
9+
/// </summary>
10+
public class PermalinkDetectedEventArgs : EventArgs
11+
{
12+
/// <summary>
13+
/// System.EventArgs for Microsoft.AspNetCore.Components.NavigationManager.LocationChanged.
14+
/// </summary>
15+
public LocationChangedEventArgs LocationChangedEventArgs { get; }
16+
17+
/// <summary>
18+
/// Detected permalink value.
19+
/// </summary>
20+
public string Permalink { get; } = "";
21+
22+
/// <summary>
23+
/// Default constructor
24+
/// </summary>
25+
/// <param name="locationChangedEventArgs">NavigationManager event</param>
26+
/// <param name="permalink">Detected permalink value</param>
27+
public PermalinkDetectedEventArgs(LocationChangedEventArgs locationChangedEventArgs, string permalink)
28+
{
29+
LocationChangedEventArgs = locationChangedEventArgs;
30+
Permalink = permalink;
31+
}
32+
}
33+
}

src/Majorsoft.Blazor.Components.TestApps.Common/Components/Permalink.razor

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ textarea {
4949

5050
<div class="container-fluid p-3 mb-3 border rounded">
5151
<h3>Internal page Permalink examles:</h3>
52+
Smooth scroll: <input type="checkbox" @bind="_permalinkWatcher.SmoothScroll"/>
5253
<ul>
5354
<li><NavLink href="permalink">No permalink</NavLink></li>
5455
<li><NavLink href="permalink#does-not_exists">Non existing permalink</NavLink></li>
@@ -148,7 +149,9 @@ textarea {
148149
</div>
149150
</div>
150151

151-
@code{
152+
@inject IPermaLinkWatcherService _permalinkWatcher
153+
154+
@code {
152155
private ShowPermaLinkIcon _showIcon = ShowPermaLinkIcon.OnHover;
153156
private PermaLinkIconPosition _iconPosition = PermaLinkIconPosition.Right;
154157
private PermaLinkStyle _iconStyle;

0 commit comments

Comments
 (0)