Hi everyone ,
I tried the new Master-Detail Layout component in Hilla and could need a little help regarding the Router integration.
This is the code of my view:
import { ViewConfig } from '@vaadin/hilla-file-router/types.js';
import { AutoGrid } from '@vaadin/hilla-react-crud';
import { GridActiveItemChangedEvent, MasterDetailLayout } from '@vaadin/react-components';
import Task from 'Frontend/generated/de/rwi/hillamasterdetailpatternexample/Task';
import TaskModel from 'Frontend/generated/de/rwi/hillamasterdetailpatternexample/TaskModel';
import { TaskService } from 'Frontend/generated/endpoints';
import { useNavigate, useOutlet } from 'react-router';
export const config: ViewConfig = {
title: 'MDL Router Integration Tasks',
};
export default function MDLRouterIntegrationTasksView() {
const navigate = useNavigate();
const childView = useOutlet();
return (
<MasterDetailLayout stackOverlay forceOverlay>
<MasterDetailLayout.Master>
<AutoGrid
className="h-full"
model={TaskModel}
service={TaskService}
onActiveItemChanged={(event: GridActiveItemChangedEvent<Task>) => {
const item = event.detail.value;
if (item?.id) {
navigate(`/mdl-router-integration-tasks/${item.id}`);
}
}}
/>
</MasterDetailLayout.Master>
<MasterDetailLayout.Detail>{childView}</MasterDetailLayout.Detail>
</MasterDetailLayout>
);
}
This is the code for the child view that will be rendered in MasterDetailLayout.Detail
:
import { ViewConfig } from '@vaadin/hilla-file-router/types.js';
import { AutoForm } from '@vaadin/hilla-react-crud';
import { useSignal } from '@vaadin/hilla-react-signals';
import { Button, Icon, VerticalLayout } from '@vaadin/react-components';
import Task from 'Frontend/generated/de/rwi/hillamasterdetailpatternexample/Task';
import TaskModel from 'Frontend/generated/de/rwi/hillamasterdetailpatternexample/TaskModel';
import { TaskService } from 'Frontend/generated/endpoints';
import { useCallback, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router';
export const config: ViewConfig = {
menu: { exclude: true },
};
export default function MDLRouterIntegrationTaskView() {
const navigate = useNavigate();
const { taskId } = useParams();
const task = useSignal<Task>();
useEffect(() => {
const getTask = async (id: number) => {
task.value = await TaskService.get(id);
};
if (taskId && !Number.isNaN(taskId)) {
getTask(Number.parseInt(taskId));
}
}, [task, taskId]);
const navigateToMasterView = useCallback(() => {
navigate('/mdl-router-integration-tasks');
}, [navigate]);
return (
<VerticalLayout theme="margin">
<Button aria-label="Navigate to master view" theme="icon" onClick={navigateToMasterView}>
<Icon icon="lumo:arrow-left" />
</Button>
<AutoForm
className="w-full"
model={TaskModel}
service={TaskService}
item={task.value}
deleteButtonVisible
onDeleteSuccess={navigateToMasterView}
onSubmitSuccess={navigateToMasterView}
/>
</VerticalLayout>
);
}
Does this example follow the intended usage of Router integration, or am I missing something or am I doing something wrong?
The example code works in terms of navigation, which means I can navigate between master and detail view. But unfortunately, the master view looses its state, when the detail view is rendered. I wonder if there is a way to avoid this?
If I use the Master-Detail Layout component without Router integration, the master view keeps its state when showing the detail view, which is good. But unfortunately, without the Router integration I won’t have deep-linking for the detail view.
Is there a way to use the Master-Detail Layout component with Router integration (for deep-linking support) and without losing the state of the master view when navigating to the detail view?