aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

Nested Routing In Blazor

Open AmarjeetBanwait opened this issue 6 years ago • 45 comments

@SteveSandersonMS As 5489 is closed now. Can we put nested routing on the roadmap as it is necessary feature for routing Ref. Angular Router Outlet

AmarjeetBanwait avatar Jun 14 '19 08:06 AmarjeetBanwait

Yep, this is essential for larger applications - and enables something like 'feature modules' (as we have in Angular).

ChristianWeyer avatar Jun 18 '19 12:06 ChristianWeyer

I would like to second this request. Right now the router is meant as a single central thing that controls the routing of the whole application but this is actually a very special case. It would help a lot if you could create relative routers that will just route relatively to wherever they currently are, regardless of whether you create an SPA or whether your (server-side) Blazor app is a component on a normal server-side Razor view.

I took a deeper look at the routing components and I think what conflicts this idea the most at the moment is that the RouteTableFactory is static, so you cannot replace the route table by a custom provider (e.g. that provided the router with relative routes), and that the Router is focused on assemblies where it will look for routed components (with the @page directive which apparently gets translated into a RouteAttribute).

Other frameworks, e.g. Angular’s router, solve this by actually having routes declared at the router, instead of automatically discovering routes through the components. So what would be helpful if there was a way to provide a router with a already prepared RouteTable. I’ll try to see if that already brings me closer to what I am trying to accomplish in my situation.

[edit] Okay, this fails because all the useful things are internal, like RouteTable, RouteEntry, and TemplateParser

poke avatar Dec 12 '19 13:12 poke

@danroth27 @SteveSandersonMS Can we consider this in "blazor wasm" release or at least 5.0 previews?

AmarjeetBanwait avatar Jan 12 '20 09:01 AmarjeetBanwait

It would be great to have component->component routing. currently routing only works for pages (i.e: controllers). I would love to have a tag and have routing within that component that can load other components based on the url. Even something like <component_router><root_component/></component_router>would be ok and we register routes to components somehow.

The only way to currently do this is a root component that essentially is a giant switch to determine the state and swapout the components as required. Imagine a simple crud component. It may have to be embedded into an existing razor view due to a legacy enterprise app written with Controllers & Views (the main selling point for blazor-server). It is easier to maintain and manage 3 or 4 smaller components dedicated to the task than one component with a huge bunch of razor logic to determine the presentation.

Wayne-Mather avatar Feb 13 '20 04:02 Wayne-Mather

Hi,

If anyone comes across this thread I have created BlazorCrudComponentRouter that enables you to easily create a CRUD based razor component to make it easier to host within MVC Views.

This achieves my goal for the short term when slowly moving away from MVC Controllers & Views in 2.1 to 3.1 hosted razor components (Blazor Server).

Your main razor component then looks like this:

<CrudComponentRouter>
    <SearchComponent>
        <MySearch/>
    </SearchComponent>
    <EditComponent>
        <MyEdit/>
    </EditComponent>
    <DeleteComponent>
        <MyDelete/>
    </DeleteComponent>
    <CreateComponent>
        <MyCreate/>
    </CreateComponent>
</CrudComponentRouter>

Maybe useful for other people so it's MIT licensed until Blazor supports component based routing (if it ever will)

Wayne-Mather avatar Feb 21 '20 03:02 Wayne-Mather

Child or nested (relative) routing is very much a needed feature similar to what Angular offers but i don't see any significant progress on its availability. Is there any plans for this feature to come out soon?

furqansafdar avatar Apr 16 '20 10:04 furqansafdar

Hi,

I just built a production sit in blazor server. It is production ready. However if you want a hybrid then yes you would need my component.

I just deployed my project to production so will try to give you what you need this Sunday.

On Thu, 16 Apr 2020, 7:31 pm Furqan Safdar, [email protected] wrote:

It is very much needed for my experimental project on Blazor to see its readiness for production but i don't see any significant progress on the availability of this feature.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dotnet/aspnetcore/issues/11212#issuecomment-614547124, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACUJ2HM452XRXUL2EROE4PLRM3JODANCNFSM4HYFOZEQ .

Wayne-Mather avatar Apr 16 '20 11:04 Wayne-Mather

现在的路由功能太简陋了,希望能像angular一样。

lixiaoyuan avatar Jun 10 '20 06:06 lixiaoyuan

I support the request for nested routing. Being able to provide "Deep" links into an application is critical.

MySite.Com\customer\123\order\45\orderitem\6

kevonh avatar Jul 03 '20 00:07 kevonh

@kevoh That’s already possible with the existing router.

SteveSandersonMS avatar Jul 03 '20 08:07 SteveSandersonMS

Hi @SteveSandersonMS. Can you please share some links which explain how to achieve what kevonh asks? I'm learning Blazor and I don't find anything related. Thanks

titobf avatar Jul 03 '20 19:07 titobf

@titobf Blazor's routing system lets you accept any number of parameters. For example you could declare a route template like:

@page "/customer/{customerId}/order/{orderId}/orderitem/{orderItemId}"

Please see docs at https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-3.1#route-parameters

SteveSandersonMS avatar Jul 06 '20 09:07 SteveSandersonMS

Hi @SteveSandersonMS, I think what this is about is having a routing system similar to Angular or react-router, where @page "/customer/{customerId}/order/{orderId}/orderitem/{orderItemId}" is not an absolute route in a component, but could be relative:

CustomerComponent.razor: @page "/customer/{customerId}/ OrderComponent.razor: @page "/order/{orderId}"

And inside CustomerComponent we have some sort of route config:

        <Route path="order/{orderId}">
          <OrderComponent />
        </Route>
        <Route path="orders">
          <CustomerOrders />
        </Route>

darianferrer avatar Jul 06 '20 11:07 darianferrer

Yes, I know :) It is something we’d like to do.

I was just answering the question to give a way of achieving the desired route pattern with the existing router features.

SteveSandersonMS avatar Jul 06 '20 12:07 SteveSandersonMS

Hi @SteveSandersonMS, I think what this is about is having a routing system similar to Angular or react-router, where @page "/customer/{customerId}/order/{orderId}/orderitem/{orderItemId}" is not an absolute route in a component, but could be relative:

This, exactly! Up vote++

kevonh avatar Jul 06 '20 16:07 kevonh

Has there been any work done on this feature?

partyelite avatar Sep 22 '20 12:09 partyelite

Not in 5.0. We have focused on many other priorities. I hope it makes sense that we have to balance a lot of different priorities and customer demands.

If you're keen to advocate for this as a 6.0 feature, the most effective way to advocate for it would be describing clear and simple scenarios where you think this is needed and why the existing routing system isn't sufficient. For example, why there's a practical problem with declaring route patterns like "/customer/{customerId}/order/{orderId}/orderitem/{orderItemId}".

I'm not arguing that anyone is wrong, so please don't interpret it that way :) I'm just saying that having clearer explanations will help to make a stronger case for why this needs to be prioritised above other enhancements that are also being demanded. Hope that makes sense!

SteveSandersonMS avatar Sep 23 '20 09:09 SteveSandersonMS

@SteveSandersonMS I'm a man of a few words so I'm gonna give you an example. Please take a look at this (see Profile tab) https://scottwhittaker.net/aurelia/2016/06/12/aurelia-router-demo.html

How can we do something similar in Blazor. We are building an larger app and something like this is a must have. Currently we have somekind of hacks like CrudComponentRouter with history.replaceState but that is extremely dirty.

partyelite avatar Sep 25 '20 19:09 partyelite

It looks like something like this can also be done with nested layouts. But I don't think razor file currently supports specifying a layout file like cshtml does.

nvmkpk avatar Sep 25 '20 22:09 nvmkpk

Actually, it looks like nested layouts work in razor file as well.

nvmkpk avatar Sep 25 '20 22:09 nvmkpk

Layouts work but imagine the following example. Based on the route you need to dynamically add tab item into tab control. After a tab item is added it should render some component as it's content. The newly added tab item should have it's set of routes that change just the rendered content of the tab item component. Lets simplify and say you navigate to "/profile/username" route. In my scenario, a Profile tab item should be added into a tab control. That tab item should render a UserName component where a user can enter username and navigate to "/profile/password" route which should render in the existing Profile tab and replace the current UserName component. Something like that is not possible with nested layouts (or I'm missing something)

partyelite avatar Sep 26 '20 06:09 partyelite

@partyelite I'm facing a similar issue. Did you find any solution?

Working with tabs and routes with Blazor seems a little complicated. This is a reason to see this feature implemented.

knuxbbs avatar Oct 22 '20 13:10 knuxbbs

@knuxbbs sorry, no.. I have tried using javascript for routing inside tabs but that proved to be unreliable because of the bugs in browsers (like firefox not replacing url when pushState is used)..

partyelite avatar Oct 22 '20 17:10 partyelite

Guys, I am unable to achieve a simple routing in Blazor, to illustrate the scenario, I have a tab component containing the Tab control and within one tab item I have a TreeView component containing a TreeView control. Now when I am trying to click on the TreeView item, I am showing the related view of that particular item adjacent to it in the @Body. All looks wired-up but when I click on the TreeView item it shows the view but give me an error along with it.

Error: System.InvalidOperationException: Object of type 'BlazorApp.Pages.TabComponent' does not have a property matching the name 'Body'.

  • TabComponent (@page “/tab”) - containing Tab control
    • TreeViewComponent (@page “/tab/treeview”) - containing TreeView control and @Body
      • @Body (@page “/tab/treeview/view1”) to show selected TreeView item (View1) component

I don’t understand why is it complaining to have a Body at TabComponent level which is seemingly unnecessary. How can I smoothly work out this simple routing?

furqansafdar avatar Jan 04 '21 05:01 furqansafdar

Hi @furqansafdar. I think we'd need to see more of your component code to understand what's going on. Maybe open a new issue for this with a link to a GitHub repo we can look at?

danroth27 avatar Jan 05 '21 01:01 danroth27

Hi @danroth27. I am providing the code reference below (simplified) to show the relevant parts only. Please note that i am using Tab control from Razden library, however TreeView control custom made but i don't see any problem with that because it is just rendering the view in the @Body on TreeView node selection using NavigationManager.NavigateTo().

I have also asked the same question on this SO Link.

TabComponent.razor

@page "/tab"
@inherits ComponentBase

<BSTabGroup>
    <BSTabList>
        <BSTab>
            <BSTabLabel>TreeView</BSTabLabel>
            <BSTabContent>
                <TreeViewComponent></TreeViewComponent>
            </BSTabContent>
        </BSTab>
    </BSTabList>
    <BSTabSelectedContent></BSTabSelectedContent>
</BSTabGroup>

TreeViewComponent.razor

@page "/tab/treeview"
@layout TabComponent
@inherits LayoutComponentBase
<div class="container remove-margin">
    <div class="row">
        <div class="col-md-3">
            <TreeView Data="TreeDataSource" NodeSelected="@TreeNodeSelect"></TreeView>
        </div>
        <div class="col-md-9" style="height: 100%">
            <div class="card" style="height: 100%">
                <div class="card-header">
                    @Body
                </div>
            </div>
        </div>
    </div>
</div>

@code {
    protected void TreeNodeSelect(object args)
    {
        NavigationManager.NavigateTo("/tab/treeview/view1");
    }
}

View1Component.razor

@page "/tab/treeview/view1"
@inherits ComponentBase
@layout TreeViewComponent

<h1>View 1</h1>

furqansafdar avatar Jan 05 '21 10:01 furqansafdar

@furqansafdar I filed https://github.com/dotnet/aspnetcore/issues/29049 to track your issue. Let's continue the discussion there.

danroth27 avatar Jan 05 '21 17:01 danroth27

This should also make possible to force re-rendering of an area of a composable component with a call like _navManager.NavigateTo("/page/area-a", true);. As a minimal example, let's say the page has a list of components that have to be refreshed. As of v5, only _navManager.NavigateTo("/page", true); it's possible and you should know it's very ugly. Evolve the framework, guys! :)

lnaie avatar Mar 01 '21 20:03 lnaie

Any update on this ? I haven't seen any reference to it in ASP.NET Core 6.0 Preview 1 and 2 blog posts. It is very difficult to design a large application without this feature

chingham avatar Mar 22 '21 12:03 chingham

@chingham It's not part of the roadmap for .NET 6, but I can see the level of community interest is pretty high so there would be a strong case for either trying to attempt this if we find we have available capacity in a few months before .NET 6 ships, or trying to schedule it soon after.

As mentioned above, the best way to create a stronger justification would be giving the simplest example you can of something that isn't practical with the existing router but large numbers of developers would want to do. I know that many large applications are built with Blazor and its existing router, so it's certainly not a blocking issue for most of our larger developer groups. If you can give a really crisp and minimal example of where the pain point is, it's easier for us to prioritise it more highly. Hope that makes sense!

SteveSandersonMS avatar Mar 31 '21 10:03 SteveSandersonMS