Kendo UI AngularJs网格指令,未定义

时间:2014-09-27 21:38:21

标签: javascript angularjs kendo-ui kendo-grid

在故障单入口页面中,我有一个主要的ticketEntry.html页面,其中包含一行网格和一行付款。

加载ticketEntry.html时,它必须首先检索故障单视图模型(通过对Web API的ajax调用)。在收到故障单视图模型之前,线路和支付网格无法检索其数据。

在我目前的解决方案中,我必须在控制器中为ticketEntry.html使用$ timeout才能生效。我正在寻找一种更清洁的方式。

来自ticketEntry.html的摘录:

<div ng-controller="ticketLineController">
    <div id="ticketLineGridDiv" kendo-grid="ticketLineGrid" k-options="ticketLineGridOptions"></div>
</div>
...
<div ng-controller="ticketPaymentController">
    <div id="ticketPaymentGridDiv" kendo-grid="ticketPaymentGrid" k-options="ticketPaymentGridOptions"></div>
</div> 

在ticketEntry.html的控制器中,我有:

$timeout(function () {
    ticketService.getTicket(ticketId).then(
        function(ticket) {
            $scope.initPos(ticket);
        },
        ...);
}, 500);

$scope.initPos = function(ticket) {
    $scope.ticket = ticket;   <-- $scope.ticket is used by the line and payment grid
    $scope.$broadcast('PosReady');  <-- Tell the payment and line controllers to load their grids
}

正如你所看到的,我使用$ timeout来延迟500ms,然后我得到了票证视图模型,并向线路和支付控制器广播,他们现在可以加载他们的网格。

以下是行控制器中的监听器:

$scope.$on('PosReady', function (event) {
    $scope.ticketLineGrid.setDataSource(getGridDataSource());
    $scope.ticketLineGrid.dataSource.read(); 
});

问题是,如果我在票据输入控制器中没有使用$ timeout,那么$ scope.ticketLineGrid有时在这里未定义(与支付控制器相同)。

我尝试在票据输入控制器中使用angular.element(document).ready(function(){...}而不是$ timeout,但是没有处理这个问题。

我如何知道$ scope.ticketLineGrid(例如)何时被创建/定义?

处理此类情景的正确方法是什么?

2014年9月27日更新,以提供有关如何初始化故障单行网格的更多数据:

在ticketEntry.html的AngularJs指令中,k-options指定网格的定义对象:

<div id="ticketLineGridDiv" kendo-grid="ticketLineGrid" k-options="ticketLineGridOptions"></div>

ticketPaymentGridOptions只是一个具有定义网格的属性的对象:

$scope.ticketPaymentGridOptions = {
  autoBind: false,
  height: 143,
  columns: [
    {
        field: "payCode", title: "PayCode",
    },
    {
        field: "amount", title: "Amount", format: "{0:n2}", attributes: { style: "text-align:right" },
    },
  ],
  pageable: false,
  ...
};

2014年9月29日更新:根据Valentin的建议,这是我的解决方案

我使用两个手表 - 一个在ticketLineGrid所在的子范围内:

$scope.$watch('ticketLineGrid', function (newVal) {
  if (angular.isDefined(newVal)) {
    $scope.ticketControl.lineGridReady = true;
  }
});

一旦网格初始化,此监视器将设置父属性$ scope.ticketControl.lineGridReady = true。

父(ticketEntryController)监视lineGridReady:

$scope.$watch('ticketControl.lineGridReady', function (gridReady) {
  if (gridReady) {
    $scope.loadPage();
  }
});

$scope.loadPage = function () {
  ticketService.getTicket(ticketId).then(
    function (ticket) {
      $scope.initPos(ticket);
    }
    ...
}

不像我希望的那样干净,但肯定比使用$ timeout ...

更好

1 个答案:

答案 0 :(得分:1)

  

我怎么知道$ scope.ticketLineGrid(例如)何时被创建/定义?

您可以使用$scope.$watch声明:

$scope.$watch('ticketLineGrid', function (newVal, oldVal) {
  if(angular.isDefined(newVal)){
    // do something with it
  }
})

但是,在我看来,这样做的好方法是不是从范围属性中检索数据,而是从promise检索数据。我只会使用承诺而不会发生任何事件:

var ticketPromise = ticketService.getTicket(ticketId);

ticketPromise.then(function (ticket) {
  $scope.ticket = ticket;
});

// you know that part better than I do
var ticketLineGridPromise = ...;

$q.all([ticketPromise, ticketLineGridPromise])
  .then(function (realizations) {
    var ticket = realizations[0], ticketLineGrid = realizations[1];

    $scope.ticketLineGrid.setDataSource(getGridDataSource());
    $scope.ticketLineGrid.dataSource.read();
  })

我无法更准确,因为您的代码不清楚初始化ticketLineGrid

最后,在许多情况下,在路线声明中使用resolve条款非常方便。