【问题标题】:In UI-Router how to set component property to child state parameter value在 UI-Router 中如何将组件属性设置为子状态参数值
【发布时间】:2017-12-04 04:06:08
【问题描述】:

我有这两个路线定义,产品列表和产品详细信息:

{
  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-view 显示产品详细信息组件:

<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;
}

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

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

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

【问题讨论】:

    标签: angular angular-ui-router


    【解决方案1】:

    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

    【讨论】:

    • 我需要编译打字稿declare module '@uirouter/core' { export class UIRouterGlobals { params$:Observable&lt;StateParams&gt;; } export class UIRouter { globals: UIRouterGlobals } }
    【解决方案2】:

    您需要实现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
                    }
                });
    
        }
    

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

    【讨论】:

    • 您好,感谢您尝试回答,但我没有使用角度路由器。我正在使用UI-Router
    • Ui-Router也有resolve!只需在那里检查 -> github.com/angular-ui/ui-router/wiki 并使用 ctrl+f 搜索“解决”,它解释得很好,上面的答案与我的答案相同。
    • 我已经使用了 resolve,请在我的问题中查看我的代码 sn-p。你的意思是说我可以从解析中获取子参数值吗?怎么样?
    • 你可以在你的组件中注入一个服务来跟踪每一个变化,并使用它来访问你的子参数。由于即使您不进行刷新也会调用解析器的逻辑,因此您可以添加几行代码来“保存”您当前的状态。
    • 这可能行得通,虽然我觉得有点老套。如果没有其他选择,我会这样做。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多