在选择最后一个按钮之前,AngularJS 单选按钮未标记为 $dirty
Posted
技术标签:
【中文标题】在选择最后一个按钮之前,AngularJS 单选按钮未标记为 $dirty【英文标题】:AngularJS radio buttons not marked $dirty until last button selected 【发布时间】:2014-04-06 13:11:04 【问题描述】:我创建了这个简单的例子:http://jsfiddle.net/5Bh59/。
如果您在 AngularJS 1.2.1 和 1.1.1 之间切换,您会看到单选按钮在任一版本中都无法正常工作。如果你看单选按钮的$dirty
字段,1) 对于版本 1.1.1,它只会在点击第一个按钮时设置,2) 对于版本 1.2.1,它只会在最后一个按钮被点击时设置点击。
我读了这个答案:AngularJS Radio group not setting $dirty on field 但我不太明白答案。不仅如此,fiddler 示例也演示了相同的行为。
那么,这是 AngularJS 中的一个错误吗?我该如何解决?
【问题讨论】:
那行得通。我很惊讶$valid
变成 true
对于两个控件,即使只选择了一个。
我猜那是因为他们使用相同的 ng-model,所以所有的输入都可以判断组中是否有一个被选中。
问题是每个人现在也有自己的$dirty
。我只喜欢在控件标记为 $dirty
时显示验证。
您可以在所有单选按钮周围包裹一个 ng-form 并将其命名为“radioGroup”,然后只要单击任何单选按钮,它就会被标记为 $dirty。我将添加另一个小提琴。
【参考方案1】:
您需要为每个单选按钮输入一个不同的名称,或者您需要将每个单选按钮包装在一个 ng-form 中(每个单选按钮都有不同的名称)。如果在同一个表单中使用两个同名的输入,则只有最后一个会绑定到 FormController 上的属性。如果您使用不同的名称,那么每个输入在 FormController 上都有自己的属性。
每个单选按钮具有不同名称的示例: http://jsfiddle.net/BEU3V/
<form name="form" novalidate>
<input type="radio"
name="myRadio1"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
<input type="radio"
name="myRadio2"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
Form $dirty: form.$dirty<br />
Field1 $dirty: form.myRadio1.$dirty<br />
Field1 $dirty: form.myRadio2.$dirty<br />
Value: myRadio
</form>
使用 ng-form 包装的示例: http://jsfiddle.net/39Rrm/1/
<form name="form" novalidate>
<ng-form name="form1">
<input type="radio"
name="myRadio"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
</ng-form>
<ng-form name="form2">
<input type="radio"
name="myRadio"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
</ng-form>
Form $dirty: form.$dirty<br />
Field1 $dirty: form.form1.myRadio.$dirty<br />
Field2 $dirty: form.form2.myRadio.$dirty<br />
Value: myRadio
</form>
如果您想对单选组进行一次检查,您可以将所有单选按钮包装在它们自己的 ng-form 中,并将其命名为 name="radioGroup"。
http://jsfiddle.net/6VVBL/
<form name="form" novalidate>
<ng-form name="radioGroup">
<input type="radio"
name="myRadio1"
ng-model="myRadio"
ng-click=""
value="Rejected"
required>Rejected<br />
<input type="radio"
name="myRadio2"
ng-model="myRadio"
ng-click=""
value="Approved"
required>Approved<br />
</ng-form>
Form $dirty: form.$dirty<br />
Group $valid: form.radioGroup.$valid<br />
Group $dirty: form.radioGroup.$dirty<br />
Value: myRadio
</form>
【讨论】:
我最终选择了选项 #3。我正在使用一个验证指令,它将用<div class="has-error">
包围一个控件并添加一个描述错误的<span>
。遗憾的是,它不起作用,因为有两个具有相同名称的控件,并且它仅适用于 ngModel
,而不适用于 form
。我只是复制了逻辑,使它与外部形式一起工作,现在一切正常。
在一个地方总结所有不同的方法也是一件好事。
觉得“如果你在同一个表单中使用两个同名的输入,那么只有最后一个会被绑定到表单上的属性”。 html 要求来自同一组的收音机具有相同的名称。然而它会在 Angular 中做这个奇怪的事情......也许 Angular 需要重新审视它如何处理收音机/复选框
如果想使用$touched
属性,这也是行不通的。实际引入类似于 Material Design 的 md-radio-group directive 的不同/自定义指令可能是有意义的【参考方案2】:
这个答案是相关的,但可能并不完全适用,但是在找到并阅读了这个项目后,我觉得提供它很有价值,而且我没有足够的分数来评论一个答案(我认为这会是一个更适当的回应方式)。
我的问题是我想显示一个必需的错误(使用 ng-messages),但是当您通过/越过单选按钮组时,除非您从下一个 UI 元素返回,否则 $touched 不会变为真到组的最后一个单选按钮。 (当我的表单呈现单选按钮时,我希望用户做出选择,而不是依赖用户接受默认值。)
这是我的代码:
<div class="form-group" ng-class="'has-error': pet.genderId.$invalid && pet.genderId.$touched">
<label class="control-label">
What is your pet's gender?
<span ng-messages="pet.genderId.$error" ng-show="pet.genderId.$invalid && pet.genderId.$touched">
<span ng-message="required">(required)</span>
</span>
</label>
<div>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="1" required ng-blur="pet.genderId.$setTouched();" />Male</label>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="2" required ng-blur="pet.genderId.$setTouched();" />Female</label>
<label class="radio-inline"><input type="radio" ng-model="genderId" name="genderId" value="3" required ng-blur="pet.genderId.$setTouched();" />Not sure</label>
</div>
</div>
“魔术”是添加 ng-blur 属性来设置“已触摸”我自己,即使只有第一个单选按钮被选中。
您可以通过在 ng-changed 属性中调用 $setDirty() 对 $dirty 使用类似的策略。
【讨论】:
以上是关于在选择最后一个按钮之前,AngularJS 单选按钮未标记为 $dirty的主要内容,如果未能解决你的问题,请参考以下文章