Open id view content from Tanstack Table with Tanstack Router

Anyone has any tip how I can render a new view in the current page of a selected item ? So im using tanstack table, query and router and if I want to open a new page when clicking an item and receiving that Item id, everything works wonderfully. But my idea is to have a table and open a view next to it instead of on a new url page.
<RouterLink
to="/page/$id"
params={{ id: props.id }}
<RouterLink
to="/page/$id"
params={{ id: props.id }}
This open a new page inside the id with the router perfectly. But what if I want just to open a new component or view inside the same page ? Anyone has a tip for this ? Any tip appreciated.
27 Replies
Knox
KnoxOP13mo ago
@dan I want to do something like this. Like my code works great if I want to open a new page. But in this case I dont want a full page, I want a view that will overlap the maps component when I click on one item
function Column(props: { id: number; name: string }) {

return (
<RouterLink
to="/actions/$id"
params={{ id: props.id }}
onClick={(event: React.MouseEvent) => {
console.log("props.id", props.i);
}}
>
{props.name}
</RouterLink>
);
}
function Column(props: { id: number; name: string }) {

return (
<RouterLink
to="/actions/$id"
params={{ id: props.id }}
onClick={(event: React.MouseEvent) => {
console.log("props.id", props.i);
}}
>
{props.name}
</RouterLink>
);
}
So I would render the item settings component of the respective item id.
No description
dan
dan13mo ago
This has an example on how to do what you want https://tanstack.com/router/v1/docs/examples/react/basic-file-based You can see the _layout.tsx, this has the "main" page layout stuff, in your case the sensors, stations, last seen etc, elements. Inside the _layout folder it contains the "inner" sections, if you instead of having multiple routes there use a dynamic route ($whatever.tsx) then you can have that be loaded and fetch the data and render as needed.
React Router Basic File Based Example | TanStack Router Docs
An example showing how to implement Basic File Based in React Router
Knox
KnoxOP13mo ago
Thank you so much. Ill take a look after lunch
dan
dan13mo ago
np, if you get stuck at all getting it working initally let me know.
Knox
KnoxOP13mo ago
@dan so I have two folder. list.items and list.items.$id on the first folder I have a +component with just
<TwoPaneLayout header={<Header />} left={<Table />} right={<Outlet />} />
<TwoPaneLayout header={<Header />} left={<Table />} right={<Outlet />} />
right will display the map when no itemId or the settings view with the itemId. for now I just leave Outlet to test somethings. my +routefile inside list.items folder has:
export const listItemsRoute = new Route({
getParentRoute: () => itemsRoute,
path: "items",
export const listItemsRoute = new Route({
getParentRoute: () => itemsRoute,
path: "items",
This loads the inicial page. Table has the same
to="/actions/$id"
params={{ id: props.id }}
to="/actions/$id"
params={{ id: props.id }}
my list.item.$id folder has a similar structure but component has
function ItemSettings() {
return (
<ContentLayout
header={
<>
<Header />
<Meta />
</>
}
content={<div>hi</div>}
/>
);
}
function ItemSettings() {
return (
<ContentLayout
header={
<>
<Header />
<Meta />
</>
}
content={<div>hi</div>}
/>
);
}
And +route
export const itemListIdRoute = new Route({
getParentRoute: () => itemsRoute,
path: "items/$itemId",
component: ItemSettings
export const itemListIdRoute = new Route({
getParentRoute: () => itemsRoute,
path: "items/$itemId",
component: ItemSettings
Im guessing this route is the problem since I cloned the project example and testing on my machine, and Im failing to see how I still have a new page.
dan
dan13mo ago
on the rootRoute have you added the children (itemListIdRoute) to listItemsRoute?
Knox
KnoxOP13mo ago
yes I did. itemRoute.addChildren([ itemListIndexRoute, itemListIdRoute, ]), Something like this
dan
dan13mo ago
oh uh try adding an index next to the dynamic route which would just be a default page when nothing is selected
Knox
KnoxOP13mo ago
I had to come on the street I’ll try and report back later 🤝
dan
dan13mo ago
AbbySalute
Knox
KnoxOP13mo ago
Aight just got home. Gonna continue to check the example and compare what im doing.
export const itemIndexRoute = new Route({
getParentRoute: () => ItemRoute,
path: "items",
validateSearch: searchSchema,
component: Item,
export const itemIndexRoute = new Route({
getParentRoute: () => ItemRoute,
path: "items",
validateSearch: searchSchema,
component: Item,
export const itemIdRoute = new Route({
getParentRoute: () => ItemRoute,
path: "items/$itemid",
component: ItemSettings,
parseParams(params) {
return {
itemId: z.number().int().parse(Number(params.itemId)),
};
},
export const itemIdRoute = new Route({
getParentRoute: () => ItemRoute,
path: "items/$itemid",
component: ItemSettings,
parseParams(params) {
return {
itemId: z.number().int().parse(Number(params.itemId)),
};
},
The only thing I can see me messing up are these +route.tsx files I have, other than that, im blind. But ill continue comparing with the folder and see what I have Ven the simple "layout A, B" should be enough to compare properly.
dan
dan13mo ago
if you have a repo I can take a look, I do remember it being a bit finicky to setup the first time.
Knox
KnoxOP13mo ago
I think I see the problem.
export const itemsRoute = new Route({
getParentRoute: () => rootRoute,
path: "items",
component: RouteItem,
});
export const itemsRoute = new Route({
getParentRoute: () => rootRoute,
path: "items",
component: RouteItem,
});
This is the main route
import { Outlet } from "@tanstack/react-router";

import Header from "./Header";

export default function RouteItem() {
return (
<div
style={{
display: "grid",
height: "100vh",
gridTemplateAreas: "'header' 'content'",
gridTemplateRows: "auto 1fr",
gridTemplateColumns: "1fr",
}}
>
<div
style={{ gridArea: "header", borderBottom: "1px solid var(--gray-a5)" }}
>
<Header />
</div>

<div
style={{
gridArea: "content",
overflow: "hidden",
}}
>
<Outlet />
</div>
</div>
);
}
import { Outlet } from "@tanstack/react-router";

import Header from "./Header";

export default function RouteItem() {
return (
<div
style={{
display: "grid",
height: "100vh",
gridTemplateAreas: "'header' 'content'",
gridTemplateRows: "auto 1fr",
gridTemplateColumns: "1fr",
}}
>
<div
style={{ gridArea: "header", borderBottom: "1px solid var(--gray-a5)" }}
>
<Header />
</div>

<div
style={{
gridArea: "content",
overflow: "hidden",
}}
>
<Outlet />
</div>
</div>
);
}
So there is an Outlet for the main page where Im going to render my page and then inside that page I want to have another Outlet. @dan I can prepare a basic repo with the necessary files if you want to take a look, but the full project is a bit large.
dan
dan13mo ago
multiple outlets is fine idm, either works, up to you really
Knox
KnoxOP13mo ago
Aight give me 5min I can wrap the files im working on together. Cant promise the code will run because probably wont but at least you can have a bigger picture
Knox
KnoxOP13mo ago
GitHub
GitHub - FACorreiaa/tanstack-router-example: tanstack router exampl...
tanstack router example to render things. Contribute to FACorreiaa/tanstack-router-example development by creating an account on GitHub.
Knox
KnoxOP13mo ago
Tell me if this would be enough to check out what im doing and not doing properly
dan
dan13mo ago
it might be the paths actually Not 100% sure but all mine are the full path, including the starting /
Knox
KnoxOP13mo ago
I guess i'll just have to continue to try and catch around the files Cuz from the example, I dont seem to be doing anything wrong. But just dont get why with the <Outlet /> the the right property, I still open a new page.
dan
dan13mo ago
Try installing the router devtools and see what routes are matching
Knox
KnoxOP13mo ago
Good idea!
Knox
KnoxOP13mo ago
No description
Knox
KnoxOP13mo ago
so /operations/sensors is the root where I see the left panel (table) and will conditionally render the right component based on the route Created a new folder just to test and changed the RouterLink to="settings" /operations/sensors/settings Open a new page And I think the base configuration is the culprit here
export const operationsRoute = new Route({
getParentRoute: () => rootRoute,
path: "operations",
component: Chrome,
});

export default function Chrome() {
return (
<div
style={{
display: "grid",
height: "100vh",
gridTemplateAreas: "'header' 'content'",
gridTemplateRows: "auto 1fr",
gridTemplateColumns: "1fr",
}}
>
<div
style={{ gridArea: "header", borderBottom: "1px solid var(--gray-a5)" }}
>
<Header />
</div>

<div
style={{
gridArea: "content",
overflow: "hidden",
}}
>
<Outlet />
<TanStackRouterDevtools />
</div>
</div>
);
}
export const operationsRoute = new Route({
getParentRoute: () => rootRoute,
path: "operations",
component: Chrome,
});

export default function Chrome() {
return (
<div
style={{
display: "grid",
height: "100vh",
gridTemplateAreas: "'header' 'content'",
gridTemplateRows: "auto 1fr",
gridTemplateColumns: "1fr",
}}
>
<div
style={{ gridArea: "header", borderBottom: "1px solid var(--gray-a5)" }}
>
<Header />
</div>

<div
style={{
gridArea: "content",
overflow: "hidden",
}}
>
<Outlet />
<TanStackRouterDevtools />
</div>
</div>
);
}
Everything is being rendered inside this <Outlet /> If I try to make something like
export const operationsRoute = new Route({
getParentRoute: () => rootRoute,
path: "operations",
component: OperationSensors,
});

export default function OperationSensors() {
return (
<MapProvider>
<TwoPaneLayout header={<Header />} left={<Table />} right={<Outlet />} />
<Outlet />
</MapProvider>
);
}
export const operationsRoute = new Route({
getParentRoute: () => rootRoute,
path: "operations",
component: OperationSensors,
});

export default function OperationSensors() {
return (
<MapProvider>
<TwoPaneLayout header={<Header />} left={<Table />} right={<Outlet />} />
<Outlet />
</MapProvider>
);
}
i'll get an error on the useQuery usage and const context = useRouteContext(routeOptions); etcetc
dan
dan13mo ago
Ah ok im starting to remember bits now Basically how I have it setup is my "layout" router (in your case operationsRoute) is using a pathless route https://avrg.dev/d3SoG.png https://avrg.dev/AvfNv.png https://avrg.dev/yaC0d.png Atm you have every router defining a path, the route you want as the layout should have an Id instead of a path.
Route Paths | TanStack Router Docs
Route paths are used to match parts of a URL's pathname to a route. At their core, route paths are just strings and can be defined using a variety of syntaxes, each with different behaviors. Before we get into those behaviors, let's look at a few important cross-cutting path concerns. Leading and Trailing Slashes
Knox
KnoxOP13mo ago
Pathless route, damn. Let me try to implement somethings after lunch and see if it fixes or changes something
Want results from more Discord servers?
Add your server