如何将组件方法分享给孩子?
Posted
技术标签:
【中文标题】如何将组件方法分享给孩子?【英文标题】:How to share component methods to child? 【发布时间】:2017-09-02 15:55:44 【问题描述】:我有两个组件:
<cmp-one></cmp-one>
被插入到 DOM 中,而我正在使用 $compile
创建一个 <cmp-top>
。
然后在cmpTop
控制器中,我需要获取<cmp-one>
并将其插入<cmp-top>
。
插入工作正常,但我需要从 cmpOne
访问 cmpTop
控制器方法 - 并且不知道如何。
到目前为止,我尝试的是添加 require: cmpTop: '^^'
- 不起作用,因为在插入完成之前没有父组件。
那么,我该如何实现呢?我的意思是 - 将一些组件插入另一个组件,并将其方法共享给添加的子组件。
更新
这里是 plunker:http://plnkr.co/edit/mgwC5Mbh5qid5q5ELDdQ?p=info
所以,我需要从DialogComponentController
访问PanelController
的方法。
或者,也许我做错了 - 所以请告诉我如何正确地做到这一点。
【问题讨论】:
你能用这个添加一个 plunker 吗? @MarcusH,我试试,谢谢关注) 是<comp-one />
在 html 中开始,然后您使用该指令来构建 <comp-top />
?
我添加了一个 plunker
在你的 plunker ccmPanel
不是 ccmDialog
的孩子(或反之亦然),他们是兄弟姐妹。这是故意的吗?
【参考方案1】:
您可以使用公共服务在它们之间进行通信(如 playerone 所述)。
app.controller('mainController', function($scope, menuSelection)
$scope.menuSelection = menuSelection; // retrieve settings object from service method and bring into scope
// now whenever one sets $scope.menuSelection.selected = "object 2", it will update the value in the other controller as well (and vice-versa)
);
app.controller('secondController', function($scope, menuSelection)
$scope.menuSelection = menuSelection; // retrieve settings object from service method and bring into scope
);
app.factory('menuSelection', function()
var settings = ;
settings.selected = 'Object 1'; // default
return settings;
);
您可以将$scope.menuSelection.myFooFunction = ...
指向一个指令中的函数并从另一个指令中调用它。
【讨论】:
为了帮助我更新了您的代码,并提供了一个当您单击面板或对话框plnkr.co/edit/IJiIsMcUWX3K9osMYuZw?p=info 时在其他组件中调用函数的示例【参考方案2】:你的代码有什么问题?
$element
.find('.panel')
.append(srcEl
.css('display', 'block')
);
您在这里使用.find
和类选择器,但根据documentation,angular 只支持标签选择器。
继承?
根据documentation
组件只控制自己的视图和数据:组件不应该修改任何超出自己范围的数据或 DOM。通常,在 AngularJS 中,可以通过范围继承和监视在应用程序的任何位置修改数据。这是实用的,但当不清楚应用程序的哪个部分负责修改数据时也会导致问题。 这就是组件指令使用隔离范围的原因,因此不可能进行整个范围的操作。
那么如何共享方法呢?
@K Scandrett 的回答很棒,可能是最佳实践,但我最喜欢的解决方案是:
在 DialogComponentController 中:
$rootScope.$emit("abc");
在面板控制器中:
$rootScope.$on("abc",function()
console.log("got it");
//and do whatever you want
);
【讨论】:
【参考方案3】:检查这个工作示例。
var app = angular.module('plunker', []);
PanelController.$inject = ['$element'];
function PanelController($element)
var $ctrl = this;
$ctrl.showAlert = function ()
alert('Message from PanelController');
;
$ctrl.close = function ()
// $element.remove();
;
$ctrl.onShow = function ()
;
$ctrl.$onInit = $onInit;
$ctrl.$onDestroy = $onDestroy;
function $onInit()
var srcEl = angular.element(document.querySelector($ctrl.source));
srcEl.attr('panel', '$ctrl');
$element
.find('.panel')
.append(srcEl
.css('display', 'block')
);
$ctrl.onShow();
var bodyRect = document.body.getBoundingClientRect(),
elRect = $element[0].getBoundingClientRect(),
position =
left: '',
top: '',
right: '',
bottom: ''
;
position.top = (bodyRect.height - elRect.height) / 4; //eslint-disable-line no-magic-numbers
position.left = (bodyRect.width - elRect.width) / 2; //eslint-disable-line no-magic-numbers
$element.css('top', position.top + 'px');
$element.css('left', position.left + 'px');
function $onDestroy()
function DialogComponentController()
var $ctrl = this;
$ctrl.callPanelMethod = function ()
var scope = angular.element($('ccm-panel div')).scope();
scope.$ctrl.showAlert();
$ctrl.actions =
close: function (event, button)
event.preventDefault();
event.stopPropagation();
$ctrl.instance.hide(button);
;
$ctrl.$onInit = $onInit;
$ctrl.$onDestroy = $onDestroy;
$ctrl.$onChanges = function ()
;
function $onInit()
function $onDestroy()
app.component('ccmDialog',
template: '<div style="border: 1px solid green; margin: 5px" >dialog <button ng-click="$ctrl.callPanelMethod()">click here to get alert from controll PanelController </button></div>',
controller: DialogComponentController,
bindings:
panel: '<',
panelShown: '&'
);
app.component('ccmPanel',
template: '<div>' +
'<div style="border: 1px solid red" class="panel" ng-click="$ctrl.close()">panel</div>' +
'</div>',
controller: PanelController,
bindings:
source: '='
);
app.controller('MainCtrl', function ($rootScope, $scope, $compile)
$scope.name = 'World';
$scope.open = function (source, target)
var scope = $rootScope.$new();
scope.$ctrl =
source: source
;
var el = $compile('<ccm-panel source="$ctrl.source" style="position: absolute;"></ccm-panel>')(scope);
angular.element(document.querySelector(target)).append(el);
);
<script data-require="angular.js@1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
<p>Hello name!</p>
<button ng-click="open('ccm-dialog', 'body')">open dialog</button>
<ccm-dialog panel="test" style="display: none"></ccm-dialog>
</div>
【讨论】:
以上是关于如何将组件方法分享给孩子?的主要内容,如果未能解决你的问题,请参考以下文章