【问题标题】:How to know when the ngModel of a select refers to an unknown option in ngOptions如何知道选择的 ngModel 何时引用 ngOptions 中的未知选项
【发布时间】:2014-09-12 21:04:46
【问题描述】:

我有两个基于通用数据集“选项”的级联下拉菜单。第一个选择的值过滤第二个选择中可用的选项。

<label for="select1" class="control-label">Select1</label>
<select name="select1" ng-model="select1" ng-options="option.select1 as option.select1 for option in options | unique: 'select1' | orderBy: 'select1'">
</select>

<label for="select2" class="control-label">Select2</label>
<select name="select2" ng-model="select2" ng-options="option.select2 as option.select2 for option in options | filter: {select1: select1} | unique: 'select2' | orderBy: 'select2'">
</select>

当用户更改 select1 中的值时,已在 select2 中选择的值可能仍然可用,也可能不可用。当 select2 中的值变得未知时,通过在 select 中选择未知(“?”) val 来反映这一点,但它不会更改模型。

问题是我不知道如何确定何时选择了无效值。我想将其设置为 null 或至少知道该值无效。

我在jsfiddle 中放了一个这种行为的例子

我尝试创建一个指令来监听视图值的变化,并在“?”时将模型更改为空。被选中,但当 angular 将视图设置为未知值时不会触发更改事件。

.directive('known', function() {
    return {
        restrict: 'AC',
        require: ['select', '?ngModel'],
        link: function ($scope, $element, $attrs, ctrls) {

            $element.change(ctrls, function() {
                if ($element.val() == "?")
                    ctrls[1].$setViewValue(null);
            });
        }
    };
 })

感谢您的宝贵时间

编辑:

我可能会过度简化我的问题:通常有 5 个级联选择相互绑定。 Select(n+2) 取决于 select(n+1) 和 select(n)。 Select(n) 不知道依赖于他的选择,例如 select(n+1, n+2, ...)。表单是基于超级用户创建的表单视图模型动态生成的(类似于https://github.com/Selmanh/angularjs-form-builder)。

所以在我的用例中,如果我能从 select2 的角度判断该值是否无效,可能会更容易。

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    在第一个下拉菜单中使用 ng-change:

    <label for="select1" class="control-label">Select1</label>
    <select name="select1" ng-model="select1" ng-options="option.select1 as option.select1 for option in options | unique: 'select1' | orderBy: 'select1'" ng-change="select1Changed()">
    </select>
    
    <label for="select2" class="control-label">Select2</label>
    <select name="select2" ng-model="select2" ng-options="option.select2 as option.select2 for option in options | filter: {select1: select1} | unique: 'select2' | orderBy: 'select2'">
    </select>
    

    在您的控制器中:

    $scope.select1Changed = function () {
       // logic of known/unknown based on $scope.select1
    }
    

    希望这会有所帮助。

    【讨论】:

    • 你的权利,它应该做的工作。我试一试,但如果我能从 select2 的角度确定值是否不好,对我来说会更好,例如“当我的选项发生变化时,我会检查我的值是否良好”。我编辑了我的问题,试图解释原因。
    【解决方案2】:

    我终于创建了一个验证指令来监视 DOM、模型和选项集合的变化。当集合被修改时,我检查值是否“?”已在视图中被选中,如果选中则认为该值是未知的。

    它对于我的用例来说足够通用,但仍然缺少处理“跟踪者”或多项选择以适应所有情况的处理。无论如何,认为这可能会对某人有所帮助:

    .directive('known', ['$parse', function($parse) {
    
    var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
    
    return {
        restrict: 'AC',
        require: ['select', '?ngModel'],
        link: function ($scope, $element, $attrs, ctrls) {
            var optionsExp = $attrs.ngOptions,
                modelCtrl = ctrls[1];
            if (match = optionsExp.match(NG_OPTIONS_REGEXP)) {
                var valueName = match[4] || match[6],
                    keyName = match[5],
                    valueFn = $parse(match[2] ? match[1] : valueName),
                    valuesFn = $parse(match[7]);
    
                $scope.$watchCollection(valuesFn, function() {
                    modelCtrl.$setValidity('unknown', !($element.val() == "?" && modelCtrl.$viewValue));
                });
    
                modelCtrl.$parsers.unshift(function(value) {
                    // value set from view can only be a known one
                     modelCtrl.$setValidity('unknown', true);
                     return value;
                });
    
                modelCtrl.$formatters.unshift(function(value) {
                    var values = valuesFn($scope) || [];
                    var valid = false;
    
                    for (var i = 0; i < values.length; i++) {
                        var local = {};
                        local[valueName] = values[i];
                        if (value === valueFn(local)) {
                            valid = true;
                            break;
                        }
                    }
    
                    modelCtrl.$setValidity('unknown', valid);
                    return value;
                });
            }
        }
    };
    }]);
    

    jsfiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 2014-08-04
      • 2018-12-18
      • 1970-01-01
      相关资源
      最近更新 更多