在Angular中如何返回到上一页?



我的要求是:

  1. 给出搜索条件后,显示下面的搜索结果,并关注搜索结果。
  2. 然后从搜索结果中选择一行后,在另一个页面中打开RECORD,替换旧的记录。(已经使用过router.navigate()方法)。
  3. 在新页面,如果用户选择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
}
}

最新更新