【问题标题】:Cannot Access parent controller's method from the child UI无法从子 UI 访问父控制器的方法
【发布时间】:2016-07-24 08:00:09
【问题描述】:

我有一个弹出表单,里面有很多标签。

它是这样的:

index.js

vm.openCreateOrEditPropertyModal = function (resolveProperty) {
    var modalInstance = $uibModal.open({
        templateUrl: '~/App/tenant/views/propertymanagement/createOrEditPropertyModal.cshtml',
        controller: 'tenant.views.propertymanagement.createOrEditPropertyModal as vm',
       resolve: {
              resolveProperty: function () {
              return resolveProperty;
                }
               }
                });
        };

标签是这样的:

createOrEditPropertyModal.cshtml

<uib-tabset class="tab-container tabbable-line" type="pills">
  <uib-tab heading="@L("PropertyInformation")">
       <div ng-include="'~/App/tenant/views/propertymanagement/tabs/propertyForm.cshtml'"></div>
      </uib-tab>
</uib-tabset>

createOrEditPropertyModal.js

(function () {
    appModule.controller("tenant.views.propertymanagement.createOrEditPropertyModal", [
        "$scope", "resolveProperty", "localStorageService", "$uibModalInstance", function ($scope, resolveProperty, localStorageService, $uibModalInstance) {

            var vm = this;


            //to close the pop up
            vm.cancel = function () {
                $uibModalInstance.close();
            };
        }
    ]);
})();

propertyForm.cshtml

<div ng-controller="tenant.views.propertymanagement.tabs.propertyForm as vm">
    <button type="button" ng-click="vm.cancel()">@L("Close")</button>
</div>

propertyForm.js

(function () {
    appModule.controller("tenant.views.propertymanagement.propertyForm", [
        "$scope", "resolveProperty", "localStorageService", function ($scope, resolveProperty, localStorageService) {

            var vm = this;



        }
    ]);
})();

以上设置工作正常。现在我需要从子窗体(即propertyForm.cshtml)访问createOrEditPropertyModal.js 文件上的cancel() 方法。但它没有被解雇。你能告诉我该怎么做?我试过这样ng-click="$parent.cancel()"。但它不起作用。

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    您可以直接在子表单中执行vm.cancel(),因为您已经在使用controllerAs 模式。但是在您的情况下,您的控制器别名都为vm,它指的是当前的子控制器上下文。更改任一控制器别名的名称将使其正常工作。

    解决此问题的最佳方法是将您的控制器别名更改为不同的名称。控制器别名应该就像通过查看它们的名称可以假装它是哪个控制器一样。

    --

    ng-click 不起作用,因为cancel 方法不在$parent 范围内。你应该做$parent.vm.cancel()。但我不希望你在视图中使用$parent,因为这是不好的做法。

    【讨论】:

    • 实际上我的设置是这样的。我已经更新了问题。请看那个。但是 cancel() 方法没有被触发。是因为控制器的名称相同吗?我的意思是vm
    • 可能.. 尝试更改名称.. 看来它必须工作
    • 这是因为您的控制器 propertyForm as vm 正在跟踪 createOrEditPropertyModal as vm
    • 是的,现在您的第二个选项正在起作用。谢谢您。但是您能告诉我重构它的最佳方法吗?
    • 无需更改控制器代码。在控制器内var vm 只是一个变量名,它包含this 的引用,您只需要更改视图绑定。就是这样。抱歉,我的误解。 ;)
    【解决方案2】:

    我能想到三种可能的解决方案:

    1. 这是因为cancel 函数不在$parent 范围内,而是在父控制器上。实现这一点的一种方法可能是对控制器使用不同的命名:related SO answer

    2. 否则,您可以将cancel 函数放在$scope 变量上的createOrEditPropertyModal

    只需更改createOrEditPropertyModal.js

    vm.cancel = function () {
        $uibModalInstance.close();
    };
    

    $scope.cancel = function () {
        $uibModalInstance.close();
    };
    
    1. 您可以将函数传递给类似于指令的模式:related SO answer

    【讨论】:

    • 第二种解决方案可能不起作用,因为stackoverflow.com/questions/23780181/…。请告诉我,我会更新我的答案
    • 你能告诉我更多关于第二个选项的信息吗?可能是简单的代码sn-p。
    • 是的,现在它正在工作。谢谢你。但我认为这不是处理父/子引用的好方法吗?你的想法是什么?如果我更改控制器的不同名称,那么我认为我必须更改所有 UI 组件名称也没有?考虑到可维护性等,你认为哪种方法更好?
    • @Sampath 我不知道您是否尝试过,但是如果您可以在实例化时通过取消功能,我更喜欢第三个。使用命名控制器可能不是一个好主意,因为它会阻止可重用性,对于访问父级也是如此。顺便说一句,哪一个有效?如果其中一个不起作用,我宁愿删除它。
    • 您的第三种解决方案可能适用于这种情况。但是如何在控制器之间共享数据?假设我需要在我的子 ctrl 中使用父 ctrl 的 propertId。那我该怎么做呢?我必须再次面对同样的问题,不是吗?
    猜你喜欢
    • 1970-01-01
    • 2015-06-28
    • 2018-04-02
    • 2015-07-04
    • 2016-03-18
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    相关资源
    最近更新 更多