AngularJS表单中Selectize下拉框$error验证失效问题排查
在AngularJS表单中使用$error验证Selectize下拉框
嘿,这个问题我之前也踩过坑!核心原因是Selectize会完全替换原生的<select>元素,生成一套自己的DOM结构。AngularJS的表单验证系统是基于原生表单控件的事件和状态来工作的,现在原生控件被藏起来了,它根本感知不到Selectize的用户操作(比如失焦、选择值变化),所以$touched和$error.required这些状态自然不会像原生下拉框那样自动更新。
给你两个靠谱的解决方案
方案1:手动同步Selectize的交互到Angular表单状态
在Selectize的初始化代码里,加上onChange和onBlur回调,手动告诉Angular发生了什么,更新对应的表单状态:
$scope.$selectUser = $('#selectUser').selectize({ valueField: 'id', labelField: 'name', searchField: 'name', placeholder: "Search by name...", options: $scope.data.recruiter_users, create: false, sortField: { field: 'name', direction: 'asc' }, // 当用户选择值时,同步到ngModel并标记控件为已修改 onChange: function(value) { $scope.$apply(function() { $scope.selectUser = value; $scope.postJobForm.selectUser.$setDirty(); }); }, // 当下拉框失焦时,标记控件为已触碰 onBlur: function() { $scope.$apply(function() { $scope.postJobForm.selectUser.$setTouched(); }); } });
这样一来,当用户点击下拉框然后失焦,或者选择了某个值时,Angular的表单状态就会跟着更新,你的错误提示也就能正常显示了。
方案2:封装成Angular指令(适合多次使用的场景)
如果你的项目里要多次用Selectize,不如把它封装成一个Angular指令,这样可以统一处理双向绑定和表单验证,不用每次都写重复代码:
angular.module('你的项目模块名').directive('selectize', function() { return { require: 'ngModel', link: function(scope, element, attrs, ngModel) { // 初始化Selectize var selectizeInstance = element.selectize({ valueField: 'id', labelField: 'name', searchField: 'name', placeholder: "Search by name...", options: scope.data.recruiter_users, create: false, sortField: { field: 'name', direction: 'asc' }, onChange: function(value) { scope.$apply(function() { ngModel.$setViewValue(value); ngModel.$setDirty(); }); }, onBlur: function() { scope.$apply(function() { ngModel.$setTouched(); }); } })[0].selectize; // 同步Angular模型到Selectize ngModel.$render = function() { selectizeInstance.setValue(ngModel.$viewValue); }; // 页面销毁时清理Selectize实例,避免内存泄漏 scope.$on('$destroy', function() { selectizeInstance.destroy(); }); } }; });
用这个指令的话,HTML就变得很简洁:
<select class="form-control" id="selectUser" name="selectUser" ng-model="selectUser" selectize required></select> <small ng-show="postJobForm.selectUser.$error.required && postJobForm.selectUser.$touched" class="errorMsg "> Please complete this required field. </small>
这样不管用多少次Selectize,表单验证都能和原生下拉框一样正常工作啦!
内容的提问来源于stack exchange,提问作者Mr world wide
相关产品推荐
相关产品推荐

