如何正确地与从另一个控制器管理的视图进行交互?

时间:2015-09-20 21:43:54

标签: javascript angularjs events view controller

这个问题似乎过于含糊,但我想不出更好的方式来描述这个想法,所以我会试着详细解释一下。

我将MasterController附加到我的SPA应用程序的<html>标记。此MasterController包含用于控制以下UI元素的所有逻辑和模型:

  • 页面标题(<title>标记)
  • 显示当前页面标题的子标题(如客户,订单,设置等)
  • 当前登录用户的名称
  • 一些常用的操作按钮,将用于系统中的所有页面。具体而言,这些按钮为Show filtersExport data to ExcelAdd new record

虽然可以通过检测当前的ui-router状态(通过其$stateChangeSuccess事件)来管理此列表中的前两项,但最后两项(用户名和按钮)有些问题,尤其是按钮。 / p>

我可以使用$broadcast管理按钮操作,因此可以通知每个控制器有关任何按钮的点击。但这里棘手的部分是按钮可能需要不同的组合 - 一个页面可能需要所有这些按钮,另一个页面可能不需要。

让我们说,ui-router加载一些CustomersController。此时MasterController接收$stateChangeSuccess事件,默认情况下会隐藏所有按钮。

但是现在,CustomersController如何告诉MasterController,CustomersController从一开始就需要两个特定的按钮?

理论上,我可以使用CustomersController中的$emit向MasterController发送一个事件,但它感觉很难看。事件是指事件,而不是发送请求,例如“嘿,MasterController,如果你在某个范围内的某个地方,你可以请出示以下按钮吗?”。

当然,我可能错了,也许有一些方法可以使用Angular事件系统以干净的方式管理这个场景。

我想到的是,也许在$stateChangeSuccess事件中,我可以以某种方式检测我的按钮点击事件当前是否有任何监听器,然后我可以隐藏没有连接任何监听器的按钮,但是我我不确定该怎么做,而且我不确定它是否能按预期工作 - 当ui-router用另一个控制器重新创建视图时,是否会分离旧的侦听器。

2 个答案:

答案 0 :(得分:1)

如果您只是嵌套控制器,其相应的范围实际上使用原型继承。因此,您可以在MasterController中定义函数$scope.configureButtons,并从嵌套的CustomerController中的$scope调用此函数。

如果控制器没有嵌套,您可能需要求助于$rootScope.$broadcast来设置按钮。

答案 1 :(得分:0)

今天我根据@DiegoCastañoChillarón的回答得到了一个棘手的想法。我想 - 但是有可能使用ui-router来交换现有视图的控制器并且还会重新绑定$ scope吗?我是否仍然可以替换加载视图的内部部分?

事实证明它是可行的!现在我不必控制主控件中的公共视图片段,我也不需要继承或复制它们 - 我只需通过ui-router将控制器切换到所需的控制器。

像这样:

$stateProvider
    .state("customers", {
            url: "^/customers",
            views: {
                "controller": {
                    controller: "CustomerController as cntrlr"
                },                                    
                "page@customers": // <- this is important, absolute name required for ui-router to find nested view
                {
                    templateUrl: "customers"
                }
            }
        }) // other routes follow in the same manner

我的HTML看起来像这样:

<div id="routes-root" ui-view="controller">

  <div id="content-header-buttons">
      <button type="button" ng-click="master.toggleFilter()">Filter data</button>
      <button type="button" ng-click="cntrlr.exportClicked()">Export</button>
      <button type="button" ng-click="cntrlr.createNewClicked()">Create</button>
   </div>
    <div id="view-content" ui-view="page"></div>
</div>

如您所见,我离开主控制器仅控制过滤器块的可见性,这不会改变。

但是控制器本身附加到#routes-root元素,保留了内部内容,而ui-router(或Angular)足够聪明,可以将$ scope和cntrlr变量附加到已加载的控制器。然后我将内部视图加载到#view-content,它也会附加到已经加载的控制器上。