我的要求是:
- 给出搜索条件后,显示下面的搜索结果,并关注搜索结果。
- 然后从搜索结果中选择一行后,在另一个页面中打开RECORD,替换旧的记录。(已经使用过router.navigate()方法)。
- 在新页面,如果用户选择BACK超链接,用户应该看到旧的搜索页面和结果。
现在,问题是,如上文第3点所述,我无法导航到具有所有SEARCH-FORM数据和数据的原始"父页面";初始的SEARCH-FORM总是在导航(returntosearchresultpage()方法)之后出现。
你的提示和帮助将非常感激!
-- 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]
})
之后,当你导航回你的搜索组件时,它会像你期望的那样出现。
当用户进行搜索时,您需要将搜索参数放在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的方式。我一时想不起来这些方法了,但是你应该可以查一下,没有问题。
当你点击BACK时,你应该转到第二个URL,而不是第一个。
现在,当搜索页面加载时,你应该使用ActivatedRoute读取URL中的参数,然后在ngOnInit中使用URL中的参数进行搜索-或者如果URL中没有参数,则正常加载。
祝你一切顺利。J-E-S-U-S爱你:)我认为实现这一点的最干净的方法是将搜索查询存储在某个地方。无论是作为导航时的查询参数,在本地存储中还是在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 docs: 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
}
}