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

时间:2017-12-04 04:06:09

标签: angular angular-ui-router

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

{
  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输入浏览器地址栏并按Enter键。

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

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

  function ColDropdownDirective() {
    return {
      restrict: 'EA',
      scope: {
        ngModel: '=',
        choices: '='
      },
      controller: ['FxoUtils', function(_) {
        var ctrl = this;
        this.trustAsHtml = function(value) {
          return _.trustAsHtml(value);
        };

        this.update = function() {
          console.log(ctrl.ngModel.selected);
        };
      }],
      controllerAs: 'ctrl',
      bindToController: true,
      templateUrl: 'js/fxo/admin/thresholdconfig/common/common.col.dropdown.html'
    };
  }

Rx扩展程序已包含在@Component({}) class { private sub; constructor(router: UIRouter) { this.sub = router.globals.params$.subscribe(params => { this.SelectedProduct = params.productcode; }); } ngOnDestroy() { this.sub.unsubscribe(); } }

答案 1 :(得分:-1)

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

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

Resolve在路由激活之前执行路由数据检索。所以你可以指定&amp;在其他事情发生之前管理您的数据。

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

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

    }

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