我很难理解angularjs如何修改DOM,特别是关于ng-required
指令。 ng-required指令(from GitHub):
var requiredDirective = function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, elm, attr, ctrl) {
if (!ctrl) return;
attr.required = true; // force truthy in case we are on non input element
ctrl.$validators.required = function(modelValue, viewValue) {
return !attr.required || !ctrl.$isEmpty(viewValue);
};
attr.$observe('required', function() {
ctrl.$validate();
});
}
};
};
我已经使用Chrome的调试器在函数中放置了断点,而且据我所知,此代码实际上并未修改DOM中所需的值,但我可以看到required="required"
被添加并从中移除输入元素。在angularjs源代码中,DOM的实际修改发生了什么?
一个简单的测试表格:
<form>
<label>Test Select</label>
<select ng-model="testSelect" ng-required="testIsRequired">
<option>val 1</option>
<option>val 2</option>
</select>
<label>Required
<input type="checkbox" ng-model="testIsRequired" />
</label>
<label>Output</label>
<p>
Test is required: {{testIsRequired}}
</p>
<p>
Select Value: {{testSelect}}
</p>
</form>
答案 0 :(得分:0)
我终于设法在正确的地方找到了一个断点。 AngularJS为'boolean'属性设置了默认链接函数('required','disabled'等),但'multiple'属性除外。
监视布尔属性,$set
attr
方法用于更改DOM。
似乎问题中的实际requiredDirective
仅在更改ng-required值时处理更新验证。
相关代码(同样来自GitHub):
var ngAttributeAliasDirectives = {};
// boolean attrs are evaluated
forEach(BOOLEAN_ATTR, function(propName, attrName) {
// binding to multiple is not supported
if (propName === 'multiple') return;
function defaultLinkFn(scope, element, attr) {
scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
attr.$set(attrName, !!value);
});
}
var normalized = directiveNormalize('ng-' + attrName);
var linkFn = defaultLinkFn;
if (propName === 'checked') {
linkFn = function(scope, element, attr) {
// ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
if (attr.ngModel !== attr[normalized]) {
defaultLinkFn(scope, element, attr);
}
};
}
ngAttributeAliasDirectives[normalized] = function() {
return {
restrict: 'A',
priority: 100,
link: linkFn
};
};
});