The Wayback Machine - https://web.archive.org/web/20210716114027/https://github.com/dotnet/aspnetcore/issues/14962
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

Expose location changing event for NavigationManger #14962

Open
Tracked in #27883
Postlagerkarte opened this issue Oct 13, 2019 · 32 comments
Open
Tracked in #27883

Expose location changing event for NavigationManger #14962

Postlagerkarte opened this issue Oct 13, 2019 · 32 comments

Comments

@Postlagerkarte
Copy link

@Postlagerkarte Postlagerkarte commented Oct 13, 2019

The NavigationManager exposes

LocationChanged | An event that fires when the navigation location has changed.

but it does not expose a LocationChanging event.

Such an event that occurs before navigation takes place is very useful because it allows the previous view to prepare for its deactivation, for example, to display a warning, cancel navigation or silently save changes.

Can you provide such a feature or is there already another way to achieve the above?

@javiercn
Copy link
Contributor

@javiercn javiercn commented Oct 14, 2019

Thank you for your feature request @Postlagerkarte.

We'll consider this feature during the next release planning period and update the status of this issue accordingly.

@Tiberriver256
Copy link

@Tiberriver256 Tiberriver256 commented Dec 24, 2019

Not sure if this is what the OP was after with LocationChanging but it would be nice to have LocationChangeStart and LocationChangeEnd events. The use case for me would be to display a little progress bar to the user while navigation is happening.

@DanielHWe
Copy link

@DanielHWe DanielHWe commented Jan 3, 2020

It would be nice to cancel the navigation to. Use Case is that the user has unsaved changes and show an error to him so he is not leaving without save.

@Postlagerkarte
Copy link
Author

@Postlagerkarte Postlagerkarte commented Jan 3, 2020

I hope that the team decides to give us a full set of methods, properties, and events to support navigation including easy access to the navigation history.

Such an improved version of the NavigationManager would certainly allow tracking the lifetime of a navigation via events like:

Navigating
Navigated
NavigationProgress
NavigationFailed
NavigationStopped

Basically, hoping for an improved/adjusted version of the NavigationService 😃

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Mar 16, 2020

Yes, it's great being able to develop an SPA application, but when the user can navigate away with changes unsaved, and no way to warn them, that's a serious flaw. You can use the javascript window.history.forward() trick in the _Hosts.html file to force the user back, but that refreshes the page losing all unsaved changes. For critical editing, I'm starting to use a state service to preserve changes, but it's a bit of a cludge to get round the problem.

@aaronhudon
Copy link

@aaronhudon aaronhudon commented Mar 27, 2020

If anyone can post suggestions on how best to implement this in SSB without waiting for Microsoft, please do so here.

@lucianotres
Copy link

@lucianotres lucianotres commented Apr 13, 2020

And would be nice to have a way to handle history stack or just a simple "location.replace(url);"
Only way I found to do this currently, was with JS interop.
js like this:

window.controles_interop = {
    ...
    location_replace: function (url) {
        window.location.replace(url);
    }
};

then call:
await JSRuntime.InvokeVoidAsync("controles_interop.location_replace", $"/protocolo/{_id.Value}");

I mean something like this, so more practical:
_nav.NavigateTo($"/protocolo/{_id.Value}", replace: true);

@javiercn
Copy link
Contributor

@javiercn javiercn commented Apr 13, 2020

@lucianotres We are adding that in a future update I think, but you don't need anything special to do that today, you can simply call JSRuntime.InvokeAsync("location.replace", url) and that will work

@OlegQu
Copy link

@OlegQu OlegQu commented May 18, 2020

Are there any news about this issue's status?
May be there are some possibilities to override or extend functions from EventDelegator.ts or NavigationManager.ts or use own NavigationManager.cs realization with scripts duplicating above default? Sorry, if this question sounds kind of... elementary - i'm still novice at coding.

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented May 18, 2020

Hi,
I've been flat out on a project where I've resolved most of the issues I had. I'm just finishing testing and hoping to publish something covering the subject later this week/next week. My basic approach has been:

  1. Use the window.onbeforeunload event to warn the user that they are leaving the "application". You don't much control over this, but it works and users I have tested it on got the message.
    Place it in the _Host.cshtml.
  2. Use a scoped data service class to track the condition (dirty/clean) of the edited record.
  3. Use a scoped user session service class to temporarily hold page routing data while transitioning between routes. This also helps on the transition from New to Edit when first saving a record.
  4. Customize the standard router to check the save state of the record and either navigate or instruct the current page that the user is trying to leave and an "Are You Sure/Unsaved Data" action is required. Note that the NavigationManager only catches navigation changes and raises the LocationChanged event, the router registers with this event and does the actual work.

The key here is to get your head around what's actually going on, and what the various classes/objects are up to.

With this approach I no longer need to tamper with the back/forward history - the router handles "In Application" page changes and onbeforeunload warns the user if they are trying to navigate away.

Note that creating a customized version of the router isn't trivial. You will need to make copies of various other classes that are namespace restricted.

I'll put a post here when I have something polished enough to publish.

@OlegQu
Copy link

@OlegQu OlegQu commented May 18, 2020

@ShaunCurtis thanks for reply!
I already implemented steps 1 and 2. Should be enough to override OnLocationChanged event in Router class? And add there:
if (hasChanges) _jsRuntime.InvokeAsync("onbeforeHandler");
And then just change all classes referenced with Router. Or this is not so simple?
I have troubles with overriding Router, cause there are a lot of dependencies and idk how to register and use them after implementing. So I will look forward to see your approach (no matter how polished it is)!
Thanks for your attention!

@ArrowtheArcher
Copy link

@ArrowtheArcher ArrowtheArcher commented Jun 17, 2020

@ShaunCurtis struggling with step 4 cannot wrap my head around it is there any other way right now? is solution for this still in progress?

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Jun 17, 2020

I'm currently working on putting a working example together - literally as I write this. Hopefully I'll have something in the next day or two. This will include the "unwrapped" router code.

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Jun 17, 2020

I've now published the routing on GitHub with a working example project. You can install the DLL via a Nuget Package (I hope!). The source code is all there in the GitHub repository.

https://github.com/ShaunCurtis/CEC.Routing

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Jun 18, 2020

I've added a further project - CEC.FormControls - that uses the router with a more polished editor component similar to what I've been using in my projects. It uses enhanced Blazor InputBase Controls and the EditContext to manage editor control and routing. The Github repository is here:

https://github.com/ShaunCurtis/CEC.FormControls

@dfkeenan
Copy link

@dfkeenan dfkeenan commented Jul 15, 2020

I just put CEC.Routing in my project. Works quite nicely. Thanks @ShaunCurtis .

@nemtajo
Copy link

@nemtajo nemtajo commented Aug 2, 2020

Hi @ShaunCurtis. Thanks! Will this library work for web assembly project as well? I need to rewrite URL to redirect URL to always remove or always add a port. For example: localhost:5001/authorize to localhost/authorize. Is this possible with your library?

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Aug 3, 2020

Hi Nemtajo,
While the functionality isn't built in, you can download the code from the repository and add it. In your case you will need to update the _locationabsolute private property in either the OnLocationChanged or Refresh Methods in the RecordRouter class. However, if you are changing the URL then you aren't routing but doing normal navigation???

@nemtajo
Copy link

@nemtajo nemtajo commented Aug 5, 2020

I found a much simpler method, In Startup.cs of the server project I added:


            app.UseStaticFiles(new StaticFileOptions()
            {
                OnPrepareResponse = (context) =>
                {
                    var request = context.Context.Request;
                    var response = context.Context.Response;
                    UrlRewriteUtils.AddPortIfLocalHost(request, response);
                }
            });


    public class UrlRewriteUtils
    {
        public static void AddPortIfLocalHost(HttpRequest request, HttpResponse response)
       {
           string url = request.GetDisplayUrl();
            if (url.Contains("localhost/authorize"))
            {
                var newUrl = url.Replace("localhost/authorize", "localhost:5001/authorize");
                response.Redirect(newUrl.ToString(), true);
            }
        }
    }

I used this as a reference: //https://stackoverflow.com/questions/51105799/how-do-i-force-https-redirect-on-static-files-in-asp-net-core-2-1

@msftbot
Copy link
Contributor

@msftbot msftbot bot commented Oct 9, 2020

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@radderz
Copy link

@radderz radderz commented Feb 24, 2021

If a User clicks the back button on the browser on a path that shouldn't be allowed (where the back goes to a place within the same app so no full navigation) would this allow for some form of breaking that navigation?

The use case is when you have gone through a wizard, and once completed it's not ok to go back to the previous screen. You can handle this in the app but its a lot more code to handle all the instances of where I was and how I got to here type logic. If we could simple have a way to say use cannot go back or similar then you could block the user from trying to go to an unsupported location.

If this doesn't sound like a good way to handle this type of situation, how would you recommend handling it? Using a UI to show an error if the navigation history wasn't in the right order?

@ShaunCurtis
Copy link

@ShaunCurtis ShaunCurtis commented Feb 25, 2021

As a further add on to my other musings on this subject, I've worked on a slightly less radical approach that dumping the router. Sometimes being a bit revolutionary helps you think a problem through more logically! There's an article here : A-Blazor-Modal-Dialog-Editor To summarise, normal routing, but all editing/user entry wizard stuff in a Modal Dialog that locks off the rest of the screen. you still need to turn on/off the browser are you sure, but that's a issue for all SPAs.

@msftbot
Copy link
Contributor

@msftbot msftbot bot commented Apr 15, 2021

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@msftbot
Copy link
Contributor

@msftbot msftbot bot commented Jul 13, 2021

Thanks for contacting us.

We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mkArtakMSFT mkArtakMSFT removed this from 6.0-rc1 (17th Aug) in ASP.NET Core Blazor & MVC 6.0 Jul 13, 2021
@GiffenGood
Copy link

@GiffenGood GiffenGood commented Jul 15, 2021

If I am reading this correctly, this issue is not going to addressed in .net 6?

@smartprogrammer93
Copy link

@smartprogrammer93 smartprogrammer93 commented Jul 15, 2021

@GiffenGood unfortunately, you read correctly.

It puzzles me though since this is one of the most requested festures in my opinion.

@GiffenGood
Copy link

@GiffenGood GiffenGood commented Jul 15, 2021

@smartprogrammer93 This is just so disappointing. We have been waiting for this feature forever and it is just a fundamental feature for a spa. What user wants to use spa where an accidental click or keypress can result in loss of work?

@smartprogrammer93
Copy link

@smartprogrammer93 smartprogrammer93 commented Jul 15, 2021

@GiffenGood i mean there is a workaround, but you will have to copy the blazor router code from the repo and a bunch of other classes (since they sealed) just to create such a function.

@oiBio
Copy link

@oiBio oiBio commented Jul 15, 2021

We were also waiting for this, to finally fix some user requests...
Very disappointing:-(

@smartprogrammer93 do you have a link/repo to an working workaround?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment