vNext Router throws Failed to resolve VR

Experimenting with the new router’s direct routing.
I get the following trying to load a route with a parameter

------------------------------------------------------------------
index.js?81dc:52 [WDS] Live Reloading enabled.
route-context.js?d513:287 Uncaught (in promise) Error: Failed to resolve VR(viewport:’’,component:‘product’,resolution:‘dynamic’,append:false) at:
RC(path:‘app’,viewports:[VPA(state:currIsActive|nextIsScheduled,plan:‘none’,resolution:‘dynamic’,n:RN(ctx:‘app/products’,c:‘products’),c:RN(ctx:‘app/products’,c:‘products’),viewport:VP(ctx:‘app’,name:‘main’,default:‘home’,fallback:‘missing’))])
** at RouteContext.resolveViewportAgent (route-context.js?d513:287)**
** at createDirectNode (route-tree.js?685a:567)**
** at createNode (route-tree.js?685a:414)**
** at createAndAppendNodes (route-tree.js?685a:353)**
** at eval (route-tree.js?685a:350)**
** at Array.map ()**
** at createAndAppendNodes (route-tree.js?685a:349)**
** at eval (route-tree.js?685a:283)**
** at Array.map ()**
** at eval (route-tree.js?685a:282)**
resolveViewportAgent @ route-context.js?d513:287
createDirectNode @ route-tree.js?685a:567
createNode @ route-tree.js?685a:414
createAndAppendNodes @ route-tree.js?685a:353
eval @ route-tree.js?685a:350
createAndAppendNodes @ route-tree.js?685a:349
eval @ route-tree.js?685a:283
eval @ route-tree.js?685a:282
onResolve @ functions.js?1334:437
updateNode @ route-tree.js?685a:278
eval @ route-tree.js?685a:296
eval @ route-tree.js?685a:295
onResolve @ functions.js?1334:437
updateNode @ route-tree.js?685a:278
eval @ route-tree.js?685a:263
onResolve @ functions.js?1334:437
updateRouteTree @ route-tree.js?685a:262
tr.run.prev @ router.js?c06d:539
run @ router.js?c06d:228
run @ router.js?c06d:537
enqueue @ router.js?c06d:475
load @ router.js?c06d:375
LoadCustomAttribute.onClick @ load.js?2f58:38
handleEvent @ event-delegator.js?6f18:58
Promise.catch (async)
enqueue @ router.js?c06d:484
load @ router.js?c06d:375
LoadCustomAttribute.onClick @ load.js?2f58:38
handleEvent @ event-delegator.js?6f18:58
----------------------------------------------------------------------------------------------------

I don’t recognize this error, but I found that the biggest gotcha with the pointing of the link at the correct viewport. If you are making a link, not in the element that has the viewport you need to add “../” for as many elements as you are deep. So if you are on a page being loaded and you are trying to load helloworld, you would say “../helloworld”. If you are in a component on that page you would need “../../helloworld”.

There is a great 3 part tutorial on the router: Aurelia 2 live coding sneak peek: New routing features - YouTube

I don’t know if this is your problem but I hope it helps.

Thanks for the reply. If that is the case, it would be against the spirit of Aurelia’s design principles and it needs to change. Using ‘3 dots’ throws runtime error for me using the dev version. So I am not sure. I have raised an issue on this “New Direct Routing feature used from nested components fails to resolve view port #1143” - with sample code. If you have a minute check it out, try 3 dots and comment on it. Cheers.

Ok. The video suggests using the ‘2 dots’ directory hierarchy syntax and that works like you said. But again, keeping track of the nesting in a complex UI will be a problem. I hope they change it such that the router is able to figure this out.

1 Like

You can still start from the root by doing /helloworld. (Also, it’s a set of ../ for upwards traversal for each viewport, not element.)

1 Like

Yeah, sorry. For some reason the editor adds a third dot. When I try to correct it, it goes back to two. Also, as stated in the video, eventually you will just be able to name the viewport. I hope they also add where it just finds the next viewport up if none is specified.

If you look at the attachment for issue #1143 that I have raised, to fix the problem I have to use two levels up. So the main viewport is at the app level and that is the only one in the example. Then, I have to use load="../../about-page" to make the load work.

Is there an alternative @ syntax like load="about-page@mainviewport" ?
It would be much better than the traversal syntax frankly.

1 Like

The video says eventually there will be. This needs to happen. I felt the same way when I first found it. I know that some posts have said that they are still working on the router. So we will have to hope this is just a temporary symptom of the router still being in alpha.

Also, why do I have to specify one at all. Why is the nearest router not just used by default with the ability to specify if I need to. Most use cases would be handled by that, not to mention, it is the expected behavior.

Thanks. I spoke too soon. I could only skim the video as I was working. I will watch it fully later. But agree with everything you say here. It also gels with the “convention over configuration” philosophy of Aurelia.

1 Like

The target viewport for a load is resolved either from root (for absolute links, starting with /) or based on where in the “viewport tree”, in which scope, the element with the load is (relative links). So if this viewport hierarchy had been created by loaded custom elements

<app-root>
    <au-viewport name="top-viewport">

        <au-viewport name="middle-viewport">

            <au-viewport name="bottom-viewport">

            </au-viewport>
        </au-viewport>
    </au-viewport>
</app-root>

any load links in them would either search for the viewport starting in the root, if absolute, or within the same viewport/routing scope as the link, if relative. Like so

<app-root>

    <a load="/hello">Starting / makes it absolute, starts at root and finds top-viewport</a>
    <a load="hello">Relative, starts here and finds top-viewport in the same scope</a>

    <au-viewport name="top-viewport">

        <a load="/world">Starting / makes it absolute, starts at root and finds top-viewport</a>
        <a load="world">Relative, starts here and finds middle-viewport in the same scope</a>
        <a load="../world">Relative, starts here, goes up one viewport scope and finds top-viewport</a>

        <au-viewport name="middle-viewport">

            <a load="/hello-world">Starting / makes it absolute, starts at root and finds top-viewport</a>
            <a load="hello-world">Relative, starts here and finds bottom-viewport in the same scope</a>
            <a load="../hello-world">Relative, starts here, goes up one viewport scope and finds middle-viewport</a>
            <a load="../../hello-world">Relative, starts here, goes up two viewport scopes and finds top-viewport</a>

            <au-viewport name="bottom-viewport">

            </au-viewport>

            <a load="hello-world">It doesn't matter if the link is before or after the viewport in the DOM, only viewport scope matters (so this has the same effect as the one before bottom-viewport</a>

        </au-viewport>
    </au-viewport>
</app-root>

There will also be an option to “flatten” the viewport hierarchy so that all viewports will be available with the @viewport syntax, for example load="hello@middle-viewport", without the need to match viewport scope.

Impressive. I will be experimenting with this and reporting back. Thank you for the great work. :+1: