我的要求是:
现在的问题是,正如上面第3点提到的,我无法导航到包含所有SEARCH-FORM数据和数据的原始“父页面”;导航后始终会出现初始搜索表单(returnToSearchResultsPage() 方法)。
非常感谢您的提醒和帮助!
-- 1. PARENT PAGE (Search Page):
showResultsOnSubmit() {
this.showSearchResults = true;
}
=============================================================
-- 2. In results-list-component:
openRecordDetails(): void {
this.router.navigate(['individual-details']);
}
=============================================================
-- 3. CHILD PAGE (In individual-details component):
// Need to return to the search-options page with the search-results intact.
returnToSearchResultsPage() {
//this.router.navigate(['search-options']);
// this._location.back();
window.history.go(-2);
}
-- 1. PARENT PAGE (Search Page):
<div>
<div>
<h1> Search</h1>
<form #searchCriteriaForm="ngForm" (ngSubmit)="showResultsOnSubmit()">
. . .
<button type="submit" [disabled]="!searchCriteriaForm.valid">Search</button>
</form>
</div>
<!-- *** Display of the Results Form @START *** -->
<div>
<results-list [showMePartially]="showSearchResults"></results-list>
</div>
<!-- **** Display of the Results Form @END *** -->
</div>
<!-- ** Display of the Results Form @START *** -->
<div>
<results-list [showMePartially]="showSearchResults"></results-list>
</div>
<!-- *** Display of the Results Form @END ** -->
</div>
=============================================================
-- 2. In results-list-component:
<div>
<button type="button" (click)="openRecordDetails()">Open Record</button>
</div>
=============================================================
-- 3. CHILD PAGE (In individual-details component):
<form>
<a href="#" style="margin-left:20px;" *ngIf="isEditModeParent" (click)="returnToSearchResultsPage()"> Return to Search Page</a>
. . . .
</form>
您正在寻找的解决方案是在最初设置路由时使用 Angular RouterModule 中的 RouteReuseStrategy。实现后,您可以在 Route 配置中设置一个属性来指定应重用哪些组件,这意味着当您离开时,它不会被销毁并在返回时重建。
首先创建一个实现RouteReuseStrategy的服务:
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
export class RouteReuseService implements RouteReuseStrategy {
private handlers: { [key: string]: DetachedRouteHandle } = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
if (!route.routeConfig || route.routeConfig.loadChildren) {
return false;
}
let shouldReuse = false;
if (route.routeConfig.data) {
route.routeConfig.data.reuse ? shouldReuse = true : shouldReuse = false;
}
return shouldReuse;
}
store(route: ActivatedRouteSnapshot, handler: DetachedRouteHandle): void {
if (handler) {
this.handlers[this.getUrl(route)] = handler;
}
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!this.handlers[this.getUrl(route)];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig || route.routeConfig.loadChildren) {
return null;
}
return this.handlers[this.getUrl(route)];
}
shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
let reUseUrl = false;
if (future.routeConfig) {
if (future.routeConfig.data) {
reUseUrl = future.routeConfig.data.reuse;
}
}
const defaultReuse = (future.routeConfig === current.routeConfig);
return reUseUrl || defaultReuse;
}
getUrl(route: ActivatedRouteSnapshot): string {
if (route.routeConfig) {
const url = route.routeConfig.path;
return url;
}
}
}
更新您的 app.module.ts 以将其添加到提供商列表中:
import { RouteReuseStrategy } from '@angular/router';
import { RouteReuseService } from './services/route-reuse.service';
@NgModule({
declarations: [
...
],
imports: [
...
],
bootstrap: [...],
providers: [{
provide: RouteReuseStrategy,
useClass: RouteReuseService
}]
})
export class AppModule {
}
然后要使组件可重用,只需将以下内容添加到您的搜索路径中:
data: {
reuse: true
}
这是一个例子:
const routes: Routes = [{
path: 'search',
component: SearchComponent,
data: {
reuse: true
}
}, {...}, {...}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
之后,当您导航回搜索组件时,它将按您的预期显示。
我认为实现这一点的最干净的方法是将搜索查询存储在某个地方。无论是在导航时作为查询参数,在本地存储中还是在 ngrx-store(我推荐)中,完全取决于您。
为此,您将有一个操作将查询作为道具,在将当前查询存储在商店中的减速器中监视该道具。在您的组件中,您可以使用选择器从商店中选择查询。 在带有搜索栏的组件中,您必须编写如下内容:
// formControl is the control bound to the search bar
// store is an ngrx service you have to inject in the constructor
this.formControl.valueChanges.pipe(
map(query => this.store.dispatch(searchStoreQueryAction({ query }))
)
每次您在搜索栏中输入内容时,都会调度存储操作。您还可以在导航之前分派它,或者只是延迟 debounceTime 运算符的流。
Ngrx 文档:https://ngrx.io/guide/store
当您调用导航方法时,您可以将搜索表单数据放入状态对象中, 会是这样的:
openRecordDetails(): void {
this.router.navigate(['individual-details'], {state: YOUR_DATA_OBJECT});
}
当您从子页面调用
returnToSearchResultsPage
方法时,您必须将对象发送回,如下所示:
returnToSearchResultsPage() {
this.router.navigate(['search-options'], {state: this._location.getState()});
// this._location.back();
// window.history.go(-2);
}
最后一部分是在父页面中添加一个 init 方法,您将从状态对象中获取搜索表单数据:
setSearchFormDataFromPreviousPage(): void {
if (this.location.getState()) {
//your code to set your search form data
}
}
当用户进行搜索时,您需要将搜索参数放入 URL 中。例如:
http://your-domain/search-options // this should be the url when you land on the search page
http://your-domain/search-options?q=elephants // the should be the url after you do a search
Angular 有多种动态更改 URL 的方法。我一时记不起这些方法,但你应该能够毫无问题地查找它们。
然后,当您单击“返回”时,您应该转到第二个 URL,而不是第一个 URL。
现在,当搜索页面加载时,您应该使用 ActivatedRoute 读取 URL 中的参数,然后使用 ngOnInit 内 URL 中的参数进行搜索 - 或者如果 URL 中没有参数,则正常加载。