我有自定义指令tagPickerTag
,validationMessageTag
和check-valid-article-meta-tags
。用法:
<div class="my-form-group">
<lable for="create_tags">Tags</lable>
<tag-picker-tag ng-model="entityInfo.meta.tags" editable="true" name="tags" check-valid-article-meta-tags></tag-picker-tag>
<validation-message-tag ctrl="form.tags"></validation-message-tag>
</div>
这就是我定义这3条指令的方法
tagPickerTag:
<div class="tag-picker-tag">
tags
<ui-select ng-model="$parent.ngModel" ng-disabled="! editable" multiple tagging tagging-tokens="SPACE|," tagging-label="(custom 'new' label)" title="Select tags" sortable="true" theme="bootstrap" >
<ui-select-match placeholder="Enter Tags...">{{$item}}</ui-select-match>
<ui-select-choices repeat="tag in suggestedTags | filter:$select.search">
{{tag}}
</ui-select-choices>
</ui-select>
<p>Selected: {{ngModel}}</p>
</div>
'use strict'
var helper = require('../../helper.js')
var app = angular.module('custom_directive')
app.directive('tagPickerTag', [function() {
return {
restrict: 'E',
scope: {
editable: '='
},
templateUrl: '/public/common/directive/tag_picker_tag.html',
require: 'ngModel',
link:
function(scope, element, attrs, ngModelCtrl) {
},
controller:
['$scope',
function($scope) {
//todo: get popular tags from server
$scope.suggestedTags = ['superbowl', '2016election']
}]}}])
checkValidArticleMetaTags:
app.directive('checkValidArticleMetaTags', helper.simpleValidationDirective('article', 'meta', 'tags'))
exports.simpleValidationDirective = function(module, nestedInParent, field) {
return function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
ctrl.$validators.checkValid = function(modelValue, viewValue) {
var validationFunction = exports.validation[module]
if (nestedInParent)
validationFunction = validationFunction[nestedInParent]
validationFunction = validationFunction[field]
var message = validationFunction(modelValue)
ctrl.data = exports.dataAppendedWithMessage({}, 'error', message)
return ! message
}
}}}}
如果您对上面代码中的validationFunction
感到好奇(它应该是无关紧要的,因为validation
指令正确地获取了验证错误消息):
....
,meta: {
tags: passIfListFulfill('tags', 10, 5, 10, false)
}
var passIfListFulfill = function(fieldName, amount, min, max, required) {
return function(input) {
if (!input || input === [])
return messageForNoInput(fieldName, required)
for (var i = 0; i < input.length; i++) {
var token = input[i]
if (token.length < min)
return token + ' is shorter than min: ' + min
else if (token.length > max)
return token + ' is longer than max ' + max
}
return messageForNoMoreThan(fieldName, input, amount)
}
}
ValidationMessageTag:
app.directive('validationMessageTag', [function() {
return {
restrict: 'E',
scope: {
ctrl: '=ngModel'
},
templateUrl: '/public/common/directive/validation_message_tag.html',
controller:
['$scope',
function($scope) {
$scope.$watch('ctrl.data', function(newValue, oldValue) {
$scope.success = newValue ? newValue.success : []
$scope.info = newValue ? newValue.info : []
$scope.warning = newValue ? newValue.warning : []
$scope.error = newValue ? newValue.error : []
}, true)
}]}}])
<div class="validation-message-tag" ng-show="ctrl.$touched && ctrl.data">
<p ng-repeat="message in success track by $index" class="validation-success">{{message}}</p>
<p ng-repeat="message in info track by $index" class="validation-info">{{message}}</p>
<p ng-repeat="message in warning track by $index" class="validation-warning">{{message}}</p>
<p ng-repeat="message in error track by $index" class="validation-error">{{message}}</p>
</div>
当我输入标签['a']
时,在我的验证指令中,我能够返回false并将字符串"a" is too short
分配给ctrl(这意味着我的验证指令是正确的)。
但是此消息未传递到我的validation_message_tag
以显示。即,不调用$watch
回调。
validtion_message_tag
适用于和标记,所以我认为问题可能是我的tagPickerTag
自定义指令的实现。
答案 0 :(得分:0)
不会调用$ watch回调。
所以我无法得到$watch
的简单方案。
我的想法是ng-model=""
是双向绑定的,你在指令中将它作为双向绑定在scope: { "ngModel" : "=" }
中取出,所以当值改变时你应该看到它反映出来。所以你不需要$watch
。但是我尝试了两种方法,但都没有效果。
所以我改为使用了事件。
$scope.$broadcast(EventNames.statusChange, vm.success)
scope.$on(EventNames.statusChange, function (e, val) { scope.show = val });
旁注,为了防止'魔术串'我从事件名称中取得了一个常数。这应该有助于消除开发人员的拼写错误
也可以在工厂完成。对于工厂,您不依赖于$scope
,因此在控制器依赖性列表中保持controllerAs
更简洁。其次,如果它不起作用,你知道它,因为工厂没有被使用,或者没有注册回调。而不是纠缠于角度事件系统的复杂事物。
关于事件聚合器模式(角$broadcast
和$on
)的旁注,在我看来,这会创建过于松散耦合的代码,导致很多speghetti代码。要考虑的另一个坏点是事件强制执行这些规则:
通过创建服务,您可以强制开发人员收听他们正在播放的内容。在registercallbacks
函数中,如果没有人注册了监听器,则可以抛出错误。此外,现在依赖于StatusService
意味着我们对组件的耦合更紧密。恕我直言,代码耦合的最佳点。
设置和收听:
StatusService.setState(vm.success);
StatusService.registerCallbacks(function (val) { scope.show2 = val });
工厂功能的实现:
function setState(value) {
for (var i = 0; i < cbs.length; i++) {
cbs[i](value);
}
}
function registerCallbacks(cb) {
cbs.push(cb);
}
基本上,它们是相同的,但在我看来,使用工厂更安全,你可以将一些逻辑抽象出工厂。而不是在回调函数中执行它。
答案 1 :(得分:0)
事实证明我设置了Cookie标记public MyFrame () {
initUI();
setVisible(true);
}
并忘记将其关闭。在进行测试时,我只是对所有验证器都返回true。