【发布时间】:2016-03-15 10:16:08
【问题描述】:
我有一个自定义指令,它使用一个属性来指定它修改的另一个控件。
指令定义对象:
{
restrict: 'E',
templateUrl: 'myTemplate.html',
scope: {
targetId: '@'
},
controller: MyController,
controllerAs: 'vm',
bindToController: true
}
指令控制器上的函数修改目标元素(输入字段)的内容:
function onSelection (value) {
var $element = $('#' + vm.targetId);
$element.val('calculated stuff');
$element.trigger('input');
}
单元测试(Jasmine/Karma/PhantomJS)当前将元素附加到页面。这行得通,但它似乎是代码异味。
beforeEach(inject(function($rootScope, $compile) {
var elementHtml = '<my-directive target-id="bar"></my-directive>' +
'<input type="text" id="bar">';
scope = $rootScope.$new();
angularElement = angular.element(elementHtml);
angularElement.appendTo(document.body); // HELP ME KILL THIS!
element = $compile(angularElement)(scope);
scope.$digest();
}));
afterEach(function () {
angularElement.remove(); // HELP ME KILL THIS!
});
我已经尝试重写控制器函数来避免使用 jQuery;这没有帮助。
如何修改指令或测试以消除 appendTo/remove?
【问题讨论】:
-
在指令中使用 id 会产生更大的代码气味。它是非常 jQuery 风格,而不是“Angular 方式”。考虑在 DOM 树的同一分支上的指令中使用
require,或者“公共父级”或“全局服务”方法(如果您不知道该怎么做,您可以搜索或询问另一个问题 - 解释肯定已经出来了这个问题的范围) -
@ValentynShybanov 我对涉及修改指令的解决方案持开放态度。该指令的实际目的是在输入或文本区域字段中插入邮件合并占位符(它不应该是指令模板的一部分,我宁愿避免嵌入)。如果您想发布推荐方法的示例或指向此的链接,我会考虑接受它作为答案。
-
我认为如果不重构
onSelection()函数,您将无法从代码中删除添加/删除元素。您是否有任何理由无法将ng-model绑定到您的#bar 输入?如果你能做到这一点,那么你可以在控制器中设置值,而无需使用 jQuery 抓取元素。 -
@jperezov 问题是指令需要目标元素中的当前选择和/或光标位置,而不仅仅是绑定文本。它在那个地方插入一个选定的值。
标签: angularjs unit-testing angularjs-directive