【问题标题】:How to render <option value="?"></option> as an error in AngularJS?如何在 AngularJS 中将 <option value="?"></option> 呈现为错误?
【发布时间】:2014-07-12 14:18:02
【问题描述】:

我有一个带有选项的选择。我想初始化关于用户登录ng-init="own = credentials.user_id"的选择值。

user_id 等于select 中的值时,它可以工作。 但是当它不等于时,选择的值是"?"。所以应该是没有错误

我不想选择这个"?" 并使表单无效。

你有解决办法吗?

<div ng-class="{ 'error-select': myForm.lead.$error.required == true }"><span>Leader</span></div>

<select ng-model="lead" name="lead" ng-options="leader.user_id as leader.user_display_name for leader in leaders" ng-init="lead = credentials.user_id" required></select> 

<div ng-class="{ 'error-select': myForm.own.$error.required == true }"><span>Leader</span></div>

<select ng-model="own" name="own" ng-options="own.user_id as own.user_display_name for own in owns" ng-init="own = credentials.user_id" required></select> 

输出:user_id = 4

  <select t ng-model="lead" name="lead" ng-options="leader.user_id as leader.user_display_name for leader in leaders" ng-init="lead = credentials.user_id" required="" class="ng-pristine ng-valid ng-valid-required">
   <option value="0">Alexandre</option>
   <option value="1">Antoine</option>
   <option value="2">Zaaza</option>
   <option value="3">toro</option>
   <option value="4"selected="selected">Steffi</option>
  </select>

  <select t ng-model="own" name="own" ng-options="own.user_id as leader.user_display_name for own in owns" ng-init="own = credentials.user_id" required="" class="ng-pristine ng-valid ng-valid-required">
   <option value="?" selected="selected"></option>
   <option value="1">Alexandre</option>
   <option value="2">Steffi</option>
  </select>

【问题讨论】:

  • 确实不会有错误,您期望什么样的错误或者您想在这种情况下显示任何消息?
  • 我想使表单无效

标签: forms angularjs select angularjs-ng-init


【解决方案1】:

这个要求并不是那么简单,可以有多种方法来解决它。 (我不确定选择的那个是最好的。)

TL;DR
这是working demo


发生了什么事?

首先要做的是:我们需要了解实际发生的情况。
控件的有效性状态 ($valid/$invalid) 取决于 $modelValue$viewValue。这里的关键点是不依赖于元素实际的value 属性。

当您尝试将$modelValue 设置为不在users 数组中的内容(例如3),即没有可用的有效&lt;option&gt; 元素时,Angular 将设置$modelValue 和@987654334 @ 到 3,但 &lt;select&gt;value 将是 ?(如果您尚未添加空的 &lt;option&gt; 元素)或任何明确添加的空 &lt;option&gt; 的值。

但由于验证不是基于元素value,从required 的角度来看,一切似乎都是$valid


解决方案

一种解决方案是创建一个自定义指令,该指令可以访问元素 ngModelController 并将自身“挂钩”到 $render() 函数。
该指令将检查元素的value 是否为?(表示无效的$modelValue),如果是,则将$modelValue/$viewValue 设置为实际为空的值,这将正确更新控件的有效性(即无效的$modelValue 将触发我们指令的处理程序将其重置为空,并且required 约束将不会被实现。

代码如下:

app.directive('select', function () {
    return {
        restrict: 'E',
        require: '?ngModel',
        priority: 10,
        link: function postLink(scope, elem, attrs, ctrl) {
            if (!ctrl) { return; }
            var originalRender = ctrl.$render.bind(ctrl);
            ctrl.$render = function () {
                originalRender();
                if ((elem.val() === '?') && !ctrl.$isEmpty(ctrl.$modelValue)) {
                    ctrl.$setViewValue(undefined);
                }
            };
        }
    };
});

另请参阅此short demo


关于上述实现的几点注意事项:

  1. 我选择将我的指令命名为select,这样它将应用于所有选择元素(与原生Angular select 指令一起——是的,这是可能的)。如果您希望仅将其应用于特定控件,请将其重命名,将其限制为属性 (restrict: 'A') 并将其作为属性添加到您的元素中。

  2. 由于(或感谢)require: '?ngModel',如果控件未绑定到 ngModel,则该控件将被忽略。

  3. 由于我们的指令扩充了ngModelController.$render() 方法,该方法由select 指令定义(以优先级0 执行),我们需要强制我们指令的链接函数在 @ 之后执行987654360@ 指令。因此,它需要更高的优先级,因为 "post-link functions are run in reverse [priority] order."

【讨论】:

    【解决方案2】:

    如果您使用 ng-required ,那么 Angular 将为您完成任务。 因此,当 ng-required 为 select 设置为 true 时,如果未为 select 设置任何值,则表单中该模型的 $error.required 将设置为 true。

    <select ng-model="lead" name="lead" ng-options="leader.user_id as leader.user_display_name for leader in leaders" ng-init="lead = credentials.user_id" ng-required="true"></select> 
    

    请找到fiddle 以获取相同的信息。如果您在脚本中注释代码

    $scope.credentials=$scope.leaders[0];
    

    错误标志将被设置,表单将无效,反之亦然。

    【讨论】:

    • 我不认为这个答案是问题所在。在这种情况下,ngRequired 的效果与required 完全相同。
    • @ExpertSystem 是的,你是对的我已经修改了我的答案。但是有了这个属性,当没有为 select 设置值并且我希望解决 OP 问题时,表单将是无效的。
    • 我认为它不会解决 OP 的问题(如他们的问题所述,将模型绑定到 ngOptions 中不存在的值时会出现问题。无论如何,您可以在我的回答中找到问题根源的详细解释和可能的解决方案。
    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 2018-09-10
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    相关资源
    最近更新 更多