表格行中的AngularJS UI-Router嵌套状态视图(内联编辑)

时间:2018-01-04 11:32:26

标签: angularjs angular-ui-router

使用AngularJS + UI-Router项目。完成了这些(简化的)要求的任务:

  • 使用表格行末尾的Edit按钮显示表格中的项目列表
  • 点击Edit按钮应将表格行转换为项目编辑表单(内联编辑)
  • 项目列表和项目编辑视图应可通过网址访问。

所以我已经定义了我的状态:

// app.js
 $stateProvider
      .state("list", {
        url: "/",
        component: "listComponent"
      })
      .state("list.edit", {
        url: "/{id}/edit",
        component: "editComponent"
      });
  }

ListComponent模板如下所示:

<table>
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>&nbsp;</th>
    </tr>
    <!-- Hide this row when NOT in edit mode -->
    <tr ng-repeat-start="item in $ctrl.items" ng-if="$ctrl.editIndex !== $index">
      <td>{{ item.id }}</td>
      <td>{{ item.name }}</td>
      <td>
        <button type="button" ng-click="$ctrl.onEditClick($index, item.id)">Edit</button>
      </td>
    </tr>
    <!-- Show this row when in edit mode -->
    <tr ng-repeat-end ng-if="$ctrl.editIndex === $index">
      <td colspan="3">
        <ui-view></ui-view>
      </td>
    </tr>
</table>

ListComponent本身的主要部分:

function ListController($state) {
    this.editIndex = null;

    this.items = [
      { id: 1, name: "Y-Solowarm" },
      // ...
      { id: 10, name: "Keylex" }
    ];

    this.onEditClick = function(index, id) {
      this.editIndex = index;
      $state.go("list.edit", { id: id });
    };
  }

问题:

当我处理EditComponent时,我注意到它启动了http请求两次。几个小时之后,我想出了EditComponent,显示了实际发生的事情:

function EditController() {
    // random number per component instance  
    this.controllerId = Math.floor(Math.random() * 100); 

    this.$onInit = function() {
      console.log("INIT:", this.controllerId);
    };

    this.$onDestroy = function() {
      console.log("DESTROY:", this.controllerId);
    };
  }

控制台显示了此输出:

DESTROY: 98 
INIT: 80
DESTROY: 80
INIT: 9

第二次点击Edit时,此输出显示

  • EditComponent#98在我们远离它时被破坏(预期)
  • EditComponent#80已创建并立即销毁(意外
  • EditComponent#9已创建,因为我们正在“修改”新项目(预期)

这只是告诉我,许多<ui-view>ng-if s一起播放不是很好,但我不知道如何解决这个问题。

我尝试过的一件事是我在<ui-view>中创建了一个ListComponent,并通过纯javascript在ui-router状态更改中移动它。但这不起作用,因为我很快就开始从ui-router的框架中获取与缺少HTML节点相关的错误。

问题:

我在这里做错了什么?我认为angular的摘要周期(以及相关的DOM更改)晚于ui-router开始转换和相关组件创建和销毁,这可能是EditComponent#80被创建并快速销毁的原因。但我不知道如何解决这个问题。

这是一个显示正在发生的事情的码本:
https://codepen.io/ramunsk/project/editor/AYyYqd
(别忘了打开开发者控制台,看看发生了什么)

由于

1 个答案:

答案 0 :(得分:1)

假设您正在从索引2切换到索引3.我认为这可能是正在发生的事情:

索引2处的ui-view当前处于活动状态。在单击处理程序中,您调用state.go,索引2处的ui-view会短暂地接收更新的状态参数id: 3。然后当ng-if生效并且创建索引3处的ui-view时,它将被销毁。

更改您的代码,使其破坏索引2 的ui-view 。添加超时,以便调用state.go显示下一个摘要周期中的第二个ui-view

this.onEditClick = function(index, id) {
  this.editIndex = null;
  $timeout(() => {
    this.editIndex = index;
    $state.go("list.edit", { id: id });
  });
};

https://codepen.io/christopherthielen/project/editor/ZyNpmv