在UI-Router中如何设置组件属性为子状态参数值

In UI-Router how to set component property to child state parameter value

我有这两个路线定义、产品列表和产品详情:

{
  name: "product",
  url: "/product",
  component: ProductListComponent,
  resolve: [
    {
      token: "Products",
      deps: [ApiService],
      resolveFn: (api: ApiService) => api.getProducts().toPromise()
    }
  ]
},
{
  name: "product.detail",
  url: "/:productcode",
  component: ProductDetailComponent,
  resolve: [
    {
      token: "Product",
      deps: [Transition, ApiService],
      resolveFn: (transition: Transition, api: ApiService) => 
        api.getProduct(transition.params().productcode).toPromise()
    }
  ]
}

在产品列表组件中,我有一组单选按钮来指示选择了哪个产品,而 ui- 视图显示产品详细信息组件:

<div *ngFor="let product of Products" class="radio">
    <label>
        <input [(ngModel)]="SelectedProduct" 
            [value]="product" 
            (change)="RefreshDetail()" 
            name="selectedProduct" 
            type="radio"> 
            {{product.Name}} {{product.Code}}
    </label>
</div>
<ui-view></ui-view>

当用户单击单选按钮时,URL、产品详细信息组件和单选按钮会正确同步。

但是当用户直接转到某个产品 URL 时,URL 和产品详细信息组件会显示正确的产品,但单选按钮不会。我所说的直接进入某个产品URL的意思是用户在浏览器地址栏输入URL并回车

我试图从 ngOnInit 中的 Transition 对象中获取 :productcode 的值:

ngOnInit() {
    let prodcode = this.transition.params().productcode;
    this.SelectedProduct = !!prodcode
        ? this.Products.find(product => product.Code == prodcode)
        : null;
}

适用于浏览器刷新,在单选按钮中选择了正确的产品。但不适用于浏览器后退按钮,没有选择单选按钮。 (可能是因为这个父状态没有重新初始化?)

无论如何,我不确定这是获取子状态参数值的惯用方法。

根据子状态参数值设置组件 属性 值的正确方法是什么?

您需要实施 Resolver。你可以在这里看看:

https://angular.io/api/router/Resolve

Resolve 在路由激活之前执行路由数据检索。因此,您可以在发生任何其他事情之前分配和管理您的数据。

这是调用某些操作时我的解析器:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<something> {
        return this.myService.getTitle(route.params[something.property])
            .do(result => {
                if (result && !!Object.keys(result).length) {
                    //action to update what you want
                } else {
                    this.notificationsService.addNotification(<Notification>{
                        text: this.localizationKeys.deletedOrNotExisting,
                        type: MessageColorType.warning
                    });
                    this.router.navigate([...])]); 
                    // tell the router where to go if there is any error
                }
            });

    }

您可以在您的组件中注入一个服务来跟踪每个更改,并使用它来访问您的子参数。由于即使您不进行刷新也会调用解析器的逻辑,因此您可以添加几行代码到 'save' 您的当前状态。

UI-Router Rx extensions 提供转换和参数流。在您的组件中,订阅参数流并更新 SelectedProduct

@Component({})
class {
  private sub;
  constructor(router: UIRouter) {
    this.sub = router.globals.params$.subscribe(params => {
      this.SelectedProduct = params.productcode;
    });
  }
  ngOnDestroy() {
    this.sub.unsubscribe();
  }
}

Rx 扩展已包含在 @uirouter/angular