我使用“动态名称属性”技术。 我正在使用 AngularJS 版本 1.5.0。 当我运行
这个AngularJS示例(下面的代码)时,它嵌套了ng-repeats(所以我使用$index
和
$parent.$index
),我希望在渲染时检查正确的单选按钮。查看下面的截图,第二组单选按钮被选中,第一组没有被选中。
<div id="app">
<div ng-controller="RadioController">
<div ng-repeat="outer_level in outer_levels">
<h1>Outer Level {{ $index }}</h1>
<div ng-repeat="inner_level in outer_level.inner_levels">
<h2>Inner Level {{ $index }}</h2>
<input
type="radio"
name="radio_{{$parent.$index}}_{{$index}}"
id="radio_{{$parent.$index}}_{{$index}}"
value="All"
ng-model="inner_level.val"
/>
<label for="radio_{{$parent.$index}}_{{$index}}"> All</label>
<input
type="radio"
name="radio_{{$parent.$index}}_{{$index}}"
id="radio_{{$parent.$index}}_{{$index}}"
value="Any"
ng-model="inner_level.val"
/>
<label for="radio_{{$index}}"> Any</label>
</div>
</div>
</div>
</div>
Javascript:
window.app = angular
.module('app', [])
.controller('RadioController', function ($scope) {
$scope.message = 'Radio';
$scope.outer_levels = [
{
inner_levels: [
{
val: 'All',
},
{
val: 'Any',
},
],
},
];
});
angular.bootstrap(document.getElementById('app'), ['app']);
单选按钮选中属性是在动态名称属性解析之前设置的。 所以所有 4 个单选按钮都使用相同的名称:
radio_{{$parent.$index}}_{{$index}}
选中第二组单选按钮,取消选中第一组单选按钮。 具体来说,在
AngularJS 源代码中,我在
radioInputType
控制器中的 $render
函数中设置了一个断点:
ctrl.$render = function() {
var value = attr.value;
// at this breakpoint, I inspect element[0], and the value of the name attribute is:
// radio_{{$parent.$index}}_{{$index}}
element[0].checked = (value == ctrl.$viewValue);
};
所以我有一些解决方法:
不要为 name 属性使用值——它是可选的,因此 AngularJS 会自动分配一个 name 属性
。 StackBlitzng-model
负责处理这个问题......(参见上面的 StackBlitz);它取消选中指向相同 ng-model
的其他单选按钮省略 name 属性可能对我来说是最好的解决方案;但稍后如何访问该控件以检查其
$error
属性或 $valid
$$parentForm
不会透露其 controls
属性,否则我可以迭代 controls
(不知道他们的名字)似乎问题出现在从$parent
(如$parent.$index
inner_level.assigned_name
-- 有效在每个
<form>
inner_level
here 演示了这将起作用。。在
这个答案中建议,但可能会影响您的表单验证。 请注意,原生 HTML
<form>
元素<form>
元素,则此解决方案将不起作用;嵌套的 <form>
元素将被忽略。
ng-form
正如 AngularJS 文档所说,“AngularJS 提供了 ngForm 指令,其行为与 form 相同,但可以嵌套”...UPDATE 选择器只是
form
<fieldset>
<fieldset>
scope.$watch(_=>element[0].name, _=>ctrl.$render());
attr
对象从第一次附加单选按钮指令时就具有正确的名称,但是 DOM
element[0].name
ng-init
$index
$parent.$index
的别名),
但它不起作用在我的示例中,我可以完全删除
{{$parent.$index}}
,它可以工作$render
函数如何在名称属性解析后触发...),但我不认为修复是在具有多个
$parent
级别的场景中就足够了...名称将不明确(即 outer_levels[0]
和 outer_levels[1]
将具有具有相同名称的单选按钮)
其他想法:也许我可以更新 Angular。当我从
id
和
name
ng-id
和
ng-name
,以便我们不使用插值,然后它开始工作。之前: <input
type="radio"
name="radio_{{$parent.$index}}_{{$index}}"
id="radio_{{$parent.$index}}_{{$index}}"
value="All"
ng-model="inner_level.val"
/>
之后:
<input
type="radio"
ng-name="'radio_' + $parent.$index + $index"
ng-id="'radio_' + $parent.$index + $index"
value="All"
ng-model="inner_level.val"
/>
window.app = angular
.module('app', [])
.controller('RadioController', function($scope) {
$scope.message = 'Radio';
$scope.val = 'All'
$scope.outer_levels = [{
inner_levels: [{
val: 'All',
},
{
val: 'Any',
},
{
val: 'Any',
},
],
}, ];
});
angular.bootstrap(document.getElementById('app'), ['app']);
<script src="https://code.angularjs.org/1.5.0/angular.min.js"></script>
<div id="app">
<div ng-controller="RadioController">
<div ng-repeat="outer_level in outer_levels">
<h1>Outer Level {{ $index }}</h1>
<div ng-repeat="inner_level in outer_level.inner_levels">
<h2>Inner Level {{ $index }}</h2>
<input
type="radio"
ng-name="'radio_' + $parent.$index + $index"
ng-id="'radio_' + $parent.$index + $index"
value="All"
ng-model="inner_level.val"
/>
<label for="radio_{{$parent.$index}}_{{$index}}"> All</label>
<input
type="radio"
ng-name="'radio_' + $parent.$index + $index"
ng-id="'radio_' + $parent.$index + $index"
value="Any"
ng-model="inner_level.val"
/>
<label for="radio_{{$index}}"> Any</label>
</div>
</div>
</div>
</div>