我想要实现的目标相对简单,但我已经用这个问题进行了很长时间,现在是时候寻求帮助了。
基本上,我创建了一个由文本输入和清除它的链接组成的指令。
我通过一个工作正常的属性传入id,但是我似乎无法弄清楚如何在点击重置链接时传递模型以清除它。
这是我到目前为止所做的:
在我看来:
<text-input-with-reset input-id="the-relevant-id" input-model="the.relevant.model"/>
我的指示:
app.directive('textInputWithReset', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<div class="text-input-with-reset">' +
'<input ng-model="inputModel" id="input-id" type="text" class="form-control">' +
'<a href class="btn-reset"><span aria-hidden="true">×</span></a>' +
'</div>',
link: function(scope, elem, attrs) {
// set ID of input for clickable labels (works)
elem.find('input').attr('id', attrs.inputId);
// Reset model and clear text field (not working)
elem.find('a').bind('click', function() {
scope[attrs.inputModel] = '';
});
}
};
});
我显然缺少一些基本的东西 - 任何帮助都会受到高度赞赏。
答案 0 :(得分:0)
在您重置值的函数中重置scope.$apply()
后,您应该致电inputModel
。
elem.find('a').bind('click', function() {
scope.inputModel = '';
scope.$apply();
});
请阅读AngularJS here中的范围。
$ apply()用于从角度框架外部以角度执行表达式。 (例如,来自浏览器DOM事件,setTimeout,XHR或第三方库)。因为我们正在调用角度框架,所以我们需要执行异常处理的适当范围生命周期,执行监视。
我还在你的指令范围内添加了inputModel
属性的声明。
scope: {
inputModel: "="
}
但是如果您可以在模板中使用ng-click - 使用它,那就更好了。
答案 1 :(得分:0)
好的,我似乎已经通过使用指令范围并在模板中使用ng-click来修复它:
我的观点:
<text-input-with-reset input-id="the-relevant-id" input-model="the.relevant.model"/>
我的指示:
app.directive('textInputWithReset', function() {
return {
restrict: 'AE',
replace: 'true',
scope: {
inputModel: '='
},
template: '<div class="text-input-with-reset">' +
'<input ng-model="inputModel" id="input-id" type="text" class="form-control">' +
'<a href ng-click="inputModel = \'\'" class="btn-reset"><span aria-hidden="true">×</span></a>' +
'</div>',
link: function(scope, elem, attrs) {
elem.find('input').attr('id', attrs.inputId);
};
});
答案 2 :(得分:0)
看起来你已经回答了你的问题,但我会在这里留下我的答案,以便进一步解释,以防其他人遇到同样的问题。
在当前状态下,您的指令有两个问题:
点击处理程序将在Angular的摘要周期之外触发。基本上,即使您设法清除模型的值,Angular也不会知道它。你可以在scope.$apply()
调用中包装你的逻辑来解决这个问题,但在这种情况下它不是正确的解决方案 - 继续阅读。
通过scope[attrs.inputModel]
访问范围会评估为scope['the.relevant.model']
。显然,模型的名称不是字面the.relevant.model
,因为点通常意味着嵌套而不是名称的字面部分。您需要一种不同的方式来引用模型。
您应该使用隔离范围(请参阅here和here)来获取此类指令。基本上,你修改你的指令看起来像这样:
app.directive('textInputWithReset', function() {
return {
restrict: 'AE',
replace: 'true',
template: [...],
// define an isolate scope for the directive, passing in these scope variables
scope: {
// scope.inputId = input-id attribute on directive
inputId: '=inputId',
// scope.inputModel = input-model attribute on directive
inputModel: '=inputModel'
},
link: function(scope, elem, attrs) {
// set ID of input for clickable labels (works)
elem.find('input').attr('id', scope.inputId);
// Reset model and clear text field (not working)
elem.find('a').bind('click', function() {
scope.inputModel = '';
});
}
};
});
请注意,在定义隔离范围时,该指令会使用请求的变量获取自己的范围。这意味着您只需在指令中使用scope.inputId
和scope.inputModel
,而不是尝试以迂回方式引用它们。
这是未经测试的,但它应该非常有效(您需要使用我之前提到的scope.$apply()
修复)。您可能希望测试inputId
绑定,因为您现在可能需要传递一个文字字符串(例如,在属性中放置'input-id'
以指定它是文字字符串,而不是{{1}这意味着范围中有一个input-id
变量。
在你的指令工作之后,让我们尝试以“Angular方式”使其更加有效。既然您的指令中有隔离范围,则无需在链接函数中实现自定义逻辑。每当您的链接函数有input-id
或.click()
时,可能有更好的方法来编写它。
在这种情况下,您可以使用更多内置的Angular逻辑来简化指令,而不是在.attr()
函数中手动修改DOM:
link()
现在,您所有的<div class="text-input-with-reset">
<input ng-model="inputModel" id="{{ inputId }}" type="text" class="form-control">
<a href="#" class="btn-reset" ng-click="reset()"><span aria-hidden="true">×</span></a>
</div>
函数(或者,更好的是,您的指令的控制器)需要做的是在作用域上定义link()
函数。其他一切都将自动生效!