UI 在 ResolveFn 的 Promise 之后路由器重定向到
UI Router RedirectTo after Promise from ResolveFn
我正在使用 Angular 2+ (targeting Angular 5) version of UI Router,但是如果有人有使用 Angular 1 版本解决同样问题的资源,我会很高兴看到——但我知道 redirectTo
属性 不是 UI 路由器早期版本的原始功能。
我有一个父组件,它的模板有 "tabs" 个,每个都命名为 <ui-view>
s.
父组件模板:
<ui-view name="child1" *ngIf="isCurrentView()"></ui-view>
<ui-view name="child2" *ngIf="isCurrentView()"></ui-view>
...
有了这个,你可以看到父模板中除了这些"tabs"之外什么都没有。所以我希望名为 'child1' 的 ui-view
成为默认视图,并且我希望它从父视图一直处于活动状态,直到用户导航到不同的路线以打开另一个 ui-视图。
假设 isCurrentView()
函数有效,并且 returns 一个布尔值,表示无论哪个视图都应该可见。一次应该只有一个视图可见。为了清楚起见,我包含此信息。
状态就是这样设置的。您注意到在 parentComponent 状态中有多个 resolveFn
。这些都调用 API 并且是异步的,在这些完成之前我们无法导航到任何 "tabs"。此设置可确保情况如此。 child1 和 child2 组件都依赖于这些响应。
{
name: "parentComponent",
url: "/parent",
component: ParentComponent,
resolve: [
{
token: "apiDetail1",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail1(); }
},
{
token: "apiDetail2",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail2(); }
}
]
},
{
name: "parentComponent.child1",
url: "/child1",
views: {
child1: { component: Child1Component }
}
},
{
name: "parentComponent.child2",
url: "/child2",
views: {
child2: { component: Child2Component }
}
}
我想在所有解析函数完成后立即重新路由到名为 parentComponent.child1 的状态——否则将无法获得必要的数据。但是我不知道该怎么做。
我知道 UI 路由器有一个 'redirectTo' 属性 然后我可以传入我的目标状态,如下所示:
redirectTo: "parentComponent.child1"
但是,redirectTo 在路由激活开始时完成。我知道我可以传入异步服务并让重定向等待该异步服务完成——但我不确定如何使用实际上在同一路由中等待解析函数的服务。
我已经调用了这些 API 一次,所以我不需要再次调用它们。在我重定向之前,我只想等待已经被调用的那两个。但是怎么办?
我找到了 答案,在移动了一些不同的东西之后。这有效,但仍然会产生我尚未诊断的控制台错误。如果有人能提供更多见解或更深入的答案,我将不胜感激。
我最后做的第一件事就是删除所有多个 <ui-view>
标签。我只在父组件模板中留下了一个未命名的标签。只有一个,我也不需要神秘的isCurrentView()
功能。
父组件模板:
<ui-view></ui-view>
州:
然后,在我的状态下,我这样定义 redirectTo
函数:
{
name: "parentComponent",
url: "/parent",
component: ParentComponent,
resolve: [
{
token: "apiDetail1",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail1(); }
},
{
token: "apiDetail2",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail2(); }
}
],
redirectTo: (transitionService: Transition) => { // This service is of type Transition, the same object you would grab parameters from
const apiCall1Promise = transitionService.injector().getAsync("apiDetail1");
const apiCall2Promise = transitionService.injector().getAsync("apiDetail2");
// I getAsync the same tokens I defined in my resolve functions
return Promise.all([apiCall1Promise, apiCall2Promise]).then(()=>{
// I don't need any of the results of the promises, since I already grab the information I need in the resolve functions, so I don't worry about getting the response here.
return "parentComponent.child1"; // Since I need to wait for both calls, I use Promise.all instead of calling the promises directly.
}).catch(() => {
return "parentComponent.child1"; // This is likely bad form, but I want it to always redirect to this state, since I do not have anything else to show the user on the current parentComponent state.
});
}
},
{
name: "parentComponent.child1",
url: "/child1",
component: Child1Component // since I'm not using named ui-view tags, I moved info out of the views property into the component property
},
{
name: "parentComponent.child2",
url: "/child2",
component: Child2Component
}
}
通过使用 getAsync() 将令牌绑定到 transitionService.injector(),然后重定向将等待对 return 的承诺。我等待我的两个解决方案(由它们的标记引用),一旦完成,我 return 我希望它导航到的路线。
但是,这样做时我仍然收到此错误:
Transition Rejection($id: 5 type: 2, message: The transition has been superseded by a different transition, detail: Transition#7( 'routeImNavigatingFrom'{} -> 'parentComponent.child1'{} ))
我不清楚这个错误是什么意思,也不清楚我为什么会收到它,因为我已经遵循了 redirectTo 文档。 There is an ongoing discussion on the error message here.
我正在使用 Angular 2+ (targeting Angular 5) version of UI Router,但是如果有人有使用 Angular 1 版本解决同样问题的资源,我会很高兴看到——但我知道 redirectTo
属性 不是 UI 路由器早期版本的原始功能。
我有一个父组件,它的模板有 "tabs" 个,每个都命名为 <ui-view>
s.
父组件模板:
<ui-view name="child1" *ngIf="isCurrentView()"></ui-view>
<ui-view name="child2" *ngIf="isCurrentView()"></ui-view>
...
有了这个,你可以看到父模板中除了这些"tabs"之外什么都没有。所以我希望名为 'child1' 的 ui-view
成为默认视图,并且我希望它从父视图一直处于活动状态,直到用户导航到不同的路线以打开另一个 ui-视图。
假设 isCurrentView()
函数有效,并且 returns 一个布尔值,表示无论哪个视图都应该可见。一次应该只有一个视图可见。为了清楚起见,我包含此信息。
状态就是这样设置的。您注意到在 parentComponent 状态中有多个 resolveFn
。这些都调用 API 并且是异步的,在这些完成之前我们无法导航到任何 "tabs"。此设置可确保情况如此。 child1 和 child2 组件都依赖于这些响应。
{
name: "parentComponent",
url: "/parent",
component: ParentComponent,
resolve: [
{
token: "apiDetail1",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail1(); }
},
{
token: "apiDetail2",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail2(); }
}
]
},
{
name: "parentComponent.child1",
url: "/child1",
views: {
child1: { component: Child1Component }
}
},
{
name: "parentComponent.child2",
url: "/child2",
views: {
child2: { component: Child2Component }
}
}
我想在所有解析函数完成后立即重新路由到名为 parentComponent.child1 的状态——否则将无法获得必要的数据。但是我不知道该怎么做。
我知道 UI 路由器有一个 'redirectTo' 属性 然后我可以传入我的目标状态,如下所示:
redirectTo: "parentComponent.child1"
但是,redirectTo 在路由激活开始时完成。我知道我可以传入异步服务并让重定向等待该异步服务完成——但我不确定如何使用实际上在同一路由中等待解析函数的服务。
我已经调用了这些 API 一次,所以我不需要再次调用它们。在我重定向之前,我只想等待已经被调用的那两个。但是怎么办?
我找到了 答案,在移动了一些不同的东西之后。这有效,但仍然会产生我尚未诊断的控制台错误。如果有人能提供更多见解或更深入的答案,我将不胜感激。
我最后做的第一件事就是删除所有多个 <ui-view>
标签。我只在父组件模板中留下了一个未命名的标签。只有一个,我也不需要神秘的isCurrentView()
功能。
父组件模板:
<ui-view></ui-view>
州:
然后,在我的状态下,我这样定义 redirectTo
函数:
{
name: "parentComponent",
url: "/parent",
component: ParentComponent,
resolve: [
{
token: "apiDetail1",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail1(); }
},
{
token: "apiDetail2",
deps: [MyAPIService],
resolveFn: (myAPIService) => { return myAPIService.getApiDetail2(); }
}
],
redirectTo: (transitionService: Transition) => { // This service is of type Transition, the same object you would grab parameters from
const apiCall1Promise = transitionService.injector().getAsync("apiDetail1");
const apiCall2Promise = transitionService.injector().getAsync("apiDetail2");
// I getAsync the same tokens I defined in my resolve functions
return Promise.all([apiCall1Promise, apiCall2Promise]).then(()=>{
// I don't need any of the results of the promises, since I already grab the information I need in the resolve functions, so I don't worry about getting the response here.
return "parentComponent.child1"; // Since I need to wait for both calls, I use Promise.all instead of calling the promises directly.
}).catch(() => {
return "parentComponent.child1"; // This is likely bad form, but I want it to always redirect to this state, since I do not have anything else to show the user on the current parentComponent state.
});
}
},
{
name: "parentComponent.child1",
url: "/child1",
component: Child1Component // since I'm not using named ui-view tags, I moved info out of the views property into the component property
},
{
name: "parentComponent.child2",
url: "/child2",
component: Child2Component
}
}
通过使用 getAsync() 将令牌绑定到 transitionService.injector(),然后重定向将等待对 return 的承诺。我等待我的两个解决方案(由它们的标记引用),一旦完成,我 return 我希望它导航到的路线。
但是,这样做时我仍然收到此错误:
Transition Rejection($id: 5 type: 2, message: The transition has been superseded by a different transition, detail: Transition#7( 'routeImNavigatingFrom'{} -> 'parentComponent.child1'{} ))
我不清楚这个错误是什么意思,也不清楚我为什么会收到它,因为我已经遵循了 redirectTo 文档。 There is an ongoing discussion on the error message here.