Skip to content

Commit

Permalink
Merge pull request #1848 from riganti/fix-viewmodel-restore
Browse files Browse the repository at this point in the history
Fix viewmodel restore on back/forward navigation
  • Loading branch information
tomasherceg authored Sep 7, 2024
2 parents 3a3f38c + 780c9d1 commit d1825a5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
18 changes: 13 additions & 5 deletions src/Framework/Framework/Resources/Scripts/dotvvm-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,19 @@ export function getStateManager(): StateManager<RootViewModel> { return getCoreS

let initialViewModelWrapper: any;

function isBackForwardNavigation() {
return (performance.getEntriesByType?.("navigation").at(-1) as PerformanceNavigationTiming)?.type == "back_forward";
}

export function initCore(culture: string): void {
if (currentCoreState) {
throw new Error("DotVVM is already loaded");
}

// load the viewmodel
const thisViewModel = initialViewModelWrapper = JSON.parse(getViewModelStorageElement().value);
const thisViewModel = initialViewModelWrapper =
(isBackForwardNavigation() ? history.state?.viewModel : null) ??
JSON.parse(getViewModelStorageElement().value);

resourceLoader.registerResources(thisViewModel.renderedResources)

Expand Down Expand Up @@ -124,8 +130,10 @@ const getViewModelStorageElement = () =>
<HTMLInputElement>document.getElementById("__dot_viewmodel_root")

function persistViewModel() {
const viewModel = getState()
const persistedViewModel = { ...initialViewModelWrapper, viewModel };

getViewModelStorageElement().value = JSON.stringify(persistedViewModel);
history.replaceState({
...history.state,
viewModel: { ...initialViewModelWrapper, viewModel: getState() }
}, "")
// avoid storing the viewmodel hidden field, as Firefox would also reuse it on page reloads
getViewModelStorageElement()?.remove()
}
41 changes: 41 additions & 0 deletions src/Samples/Tests/Tests/Complex/TaskListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,46 @@ public void Complex_TaskList_ServerRenderedTaskList()
"Last task is not marked as completed.");
});
}

[Fact]
public void Complex_TaskList_TaskListAsyncCommands_ViewModelRestore()
{
// view model should be restored after back/forward navigation, but not on refresh
RunInAllBrowsers(browser =>
{
browser.NavigateToUrl("/");
browser.NavigateToUrl(SamplesRouteUrls.ComplexSamples_TaskList_TaskListAsyncCommands);

browser.SendKeys("input[type=text]", "test1");
browser.Click("input[type=button]");

browser.FindElements(".table tr").ThrowIfDifferentCountThan(4);

browser.NavigateBack();
browser.WaitUntilDotvvmInited();
browser.NavigateForward();

browser.FindElements(".table tr").ThrowIfDifferentCountThan(4);

browser.Refresh();

browser.FindElements(".table tr").ThrowIfDifferentCountThan(3);

browser.SendKeys("input[type=text]", "test2");
browser.Click("input[type=button]");
browser.FindElements(".table tr").ThrowIfDifferentCountThan(4);

browser.NavigateToUrl("/");
browser.NavigateToUrl(SamplesRouteUrls.ComplexSamples_TaskList_TaskListAsyncCommands);

browser.FindElements(".table tr").ThrowIfDifferentCountThan(3);

browser.NavigateBack();
browser.WaitUntilDotvvmInited();
browser.NavigateBack();

browser.FindElements(".table tr").ThrowIfDifferentCountThan(4);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public void Feature_FormControlsEnabled_FormControlsEnabled()

private void TestLinkButton(IBrowserWrapper browser, string id, bool shouldBeEnabled, ref int currentPresses)
{
browser.First($"#{id}").Click();
browser.First($"#{id}").ScrollTo().Wait(500).Click();
if (shouldBeEnabled)
{
currentPresses++;
Expand Down

0 comments on commit d1825a5

Please sign in to comment.