angularjs - AngularJS 组件嵌套
问题描述
我创建了一个组件搜索上下文,效果很好。它是可配置的,它会做它应该做的事情。
<search-context context-name="Groups"
compare-columns="['displayName']"
search-manager="$ctrl"
query-url="/group/search/{{contextId}}"
icon="fa fa-users"
on-resolve-item-url="resolveItemUrl(row)"></search-context>
它在行动中,独立。
还有各种其他搜索上下文,我想创建一个搜索管理器组件,这样我就可以像这样编写标记:
<search-manager>
<search-context context-name="Devices"
compare-columns="['displayName']"
search-manager="$ctrl"
query-url="/device/search/{{contextId}}"
icon="fa fa-laptop"></search-context>
<search-context context-name="Groups"
compare-columns="['displayName']"
search-manager="$ctrl"
query-url="/group/search/{{contextId}}"
icon="fa fa-users"
on-resolve-item-url="resolveGroupEditUrl(row)"></search-context>
</search-manager>
一般的计划是搜索上下文检查它是否有搜索管理器,如果有,则抑制它自己的输入/按钮控件,搜索管理器将提供输入控件并将搜索词提供给搜索上下文。
AngularJS 组件文档中的示例演示了在控件模板中使用 ng-repeat 的动态子控件,但不清楚如何设置以处理我建议的显式标记。如果可能的话,我宁愿不需要明确指定search-manager="$ctrl"
父引用。
一个人如何去做这件事,以及必须研究和理解的支持主题是什么?只是关键概念名称会有很大帮助,但概述和进一步阅读列表会很棒。
我对模板的第一次尝试search-manager
看起来像这样
<div>
<div class="panel-heading">
<h3 class="panel-title">Search</h3>
<div class="input-group">
<input class="form-control" ng-model="$ctrl.term" />
<span class="input-group-btn" ng-click="$ctrl.search()">
<button class="btn btn-default">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</div>
<div class="panel-body">
<ng-transclude></ng-transclude>
</div>
</div>
代码看起来像这样
function SearchManagerController($scope, $element, $attrs, $http) {
var ctrl = this;
ctrl.searchContext = [];
ctrl.registerSearchContext = function (searchContext) {
ctrl.searchContext.push(searchContext);
}
ctrl.search = function () {
ctrl.searchContext.forEach(function (searchContext) {
searchContext.search(ctrl.term);
});
};
}
angular.module("app").component("searchManager", {
templateUrl: "/app/components/search-manager.html",
controller: SearchManagerController,
transclude: true,
bindings: {
term: "@"
}
});
子组件被嵌入,但它们需要对该search-manager
组件的引用,并且$ctrl
不在范围内。
我们如何获得对父级的引用?
解决方案
要获得对父级的引用,您需要做的就是声明require
中的父search-context
级。双插入符号前缀意味着搜索父母。单个插入符号从当前对象开始,它可以工作但效率稍低。问号的意思是如果找不到就不要吐槽,直接返回 undefined。当组件可能并不总是由搜索管理器作为父级时,这是必要的。
angular.module("app").component("searchContext", {
templateUrl: "/app/components/search-context.html",
controller: SearchContextController,
require: {
searchManagerCtrl: "?^^searchManager"
},
bindings: {
...
}
});
但是,如果您需要父级引用子级怎么办?
在SearchContextController
我们实现$onInit
生命周期事件处理程序。
ctrl.$onInit = function () {
if (ctrl.searchManagerCtrl) {
ctrl.searchManagerCtrl.registerSearchContext(ctrl);
}
};
registerSearchContext
是为此目的在父控制器中定义的方法。该实现本质上将每个注册的控件推送到我们在其范围内定义的数组属性中,然后父级的方法可以枚举子级。
对于指令,这个require
技巧的表达方式略有不同。您必须在指令范围内声明该属性searchManagerCtrl
,并直接提供表达式作为 require 的值。
require: "?^^searchManager",
您还必须提供一个link
函数。link
函数的参数之一是controller
,并且将在此参数中传递对的引用searchManager
,此时您可以将其分配给指令范围的属性。生命$onInit
周期事件仍可用于向搜索管理器注册,但指的是$scope
而不是ctrl
.
推荐阅读
- swift - Calendar.current.isDate equalTo toGranularity:Calendar.Component.Day 有奇怪的匹配行为
- javascript - 如何添加多个过滤器(Caman.js)?
- javascript - jQuery:从附近元素获取文本内容并打印到模式标题
- python - 抽象类中的递归 - Python
- javascript - 单击谷歌下拉项目时触发警报
- python - 使用 numpy.roll 对例程进行矢量化
- magento2 - 1 x Magento 2.2.x 多存储多域不工作
- c# - 为什么从投影创建的整数变量不能递增?
- github - Github 算不算持续集成?如果不是,Github 和持续集成有什么区别?
- javascript - 减少 React-Redux 状态和调度样板