为啥 AngularJS 在选择中包含一个空选项?
Posted
技术标签:
【中文标题】为啥 AngularJS 在选择中包含一个空选项?【英文标题】:Why does AngularJS include an empty option in select?为什么 AngularJS 在选择中包含一个空选项? 【发布时间】:2012-09-21 04:50:26 【问题描述】:过去几周我一直在使用 AngularJS,而真正困扰我的一件事是,即使在尝试了 http://docs.angularjs.org/api/ng.directive:select 规范中定义的所有排列或配置之后,我仍然得到一个空选项作为选择元素的第一个子元素。
这是玉:
select.span9(ng-model='form.type', required, ng-options='option.value as option.name for option in typeOptions');
这里是控制器:
$scope.typeOptions = [
name: 'Feature', value: 'feature' ,
name: 'Bug', value: 'bug' ,
name: 'Enhancement', value: 'enhancement'
];
最后,这是生成的 html:
<select ng-model="form.type" required="required" ng-options="option.value as option.name for option in typeOptions" class="span9 ng-pristine ng-invalid ng-invalid-required">
<option value="?" selected="selected"></option>
<option value="0">Feature</option>
<option value="1">Bug</option>
<option value="2">Enhancement</option>
</select>
我需要做什么才能摆脱它?
P.S.:没有这个也可以,但是如果你使用 select2 而没有多重选择,它看起来很奇怪。
【问题讨论】:
【参考方案1】:当ng-model
引用的值在传递给ng-options
的一组选项中不存在时,将生成空的option
。这样做是为了防止意外选择模型:AngularJS 可以看到初始模型未定义或不在选项集中,并且不想自行决定模型值。
如果您想摆脱空选项,只需在控制器中选择一个初始值,例如:
$scope.form.type = $scope.typeOptions[0].value;
这里是 jsFiddle:http://jsfiddle.net/MTfRD/3/
简而言之:空选项意味着没有选择有效的模型(有效的意思是:从选项集中)。你需要选择一个有效的模型值来去掉这个空选项。
【讨论】:
我都试过 $scope.form.type = '';和 $scope.form.type = $scope.typeOptions[0],但是我仍然认为这个 - 有时将这些数据放在 JS 中确实没有意义。如果是服务器决定了选择中的内容,为什么 JS 必须复制它? 不幸的是,如果您使用的是数组并且null
是您的值之一,这将不起作用。
是否可以在空的<option>
中添加一个文本,所以 tat angular 生成了类似<option value="?">Select an option</option>
的内容
@Tareck117 只是写<option value="">Select an option</option>
那是选项列表的空值。不需要 ?-字符。【参考方案2】:
如果您想要一个初始值,请参阅@pkozlowski.opensource 的答案,仅供参考,也可以使用 ng-init 在视图中(而不是在控制器中)实现:
<select ng-model="form.type" required="required" ng-init="form.type='bug'"
ng-options="option.value as option.name for option in typeOptions" >
</select>
如果您不想要初始值,“可以将值设置为空字符串的单个硬编码元素嵌套到元素中。然后该元素将表示 null 或“未选择”选项” :
<select ng-model="form.type" required="required"
ng-options="option.value as option.name for option in typeOptions" >
<option style="display:none" value="">select a type</option>
</select>
【讨论】:
@hugo,工作小提琴:jsfiddle.net/4qKyx/1 请注意,显示了“选择类型”,但没有与之关联的值。一旦你选择了其他东西,你就不会再看到它了。 (在 Chrome 上测试。) @MarkRajcok - 很好的建议!我偶然发现了另一个问题,使用您的包含指令的示例。你能看看吗? plnkr.co/edit/efaZdEQlNfoDihk1R1zc?p=preview 这个问题是你仍然可以用键盘选择,见***.com/a/8442831/57344解决方案 这可能暂时有效,但角度文档特别建议不要将 ng-init 用于除 ng-repeat 之外的任何内容 - 请参阅 docs.angularjs.org/api/ng/directive/ngInit 在IE10中不起作用,“选择类型”始终可见且可选择。【参考方案3】:角度
对于将“null”视为选项之一的有效值的任何人(所以想象“null”是下面示例中 typeOptions 中的项目之一的值),我发现确保隐藏自动添加的选项的最简单方法是使用 ng-if。
<select ng-options="option.value as option.name for option in typeOptions">
<option value="" ng-if="false"></option>
</select>
为什么是 ng-if 而不是 ng-hide?因为您想要将上面的第一个选项作为目标的 css 选择器选择目标“真实”选项,而不是隐藏的选项。当您使用量角器进行 e2e 测试以及(无论出于何种原因)使用 by.css() 来定位选择选项时,它会变得很有用。
角度 >= 1.4
由于对 select 和 options 指令的重构,使用 ng-if
不再是一个可行的选项,因此您必须求助于 ng-show="false"
以使其再次工作。
【讨论】:
应该是公认的答案,因为这是选择的正确视觉行为。您将size="5"
放入选择属性,您可以看到没有选择任何内容!就像在默认的 <select>
-Element 中一样!我不明白为什么 Angular 会为没有 multiple
属性的选择做这样的事情......
是的,我同意,这应该是公认的答案。这是“角度方式”。 ng-if 实际上会从 dom 中删除 options 元素(当为 false 时),因此该解决方案也适用于所有没有“hacky”编码的浏览器(与 ng-hide 或 ng-show 相反)。
@Sander_P 根据定义,在我看来,这个解决方案是“hacky”编码(在 dom 中放置一些东西来欺骗 Angular 将其取出),但你是对的,它仍然是“最佳”解决方案. “更好”的解决方案是允许一个没有价值的 friggin 选择!有没有搞错?这不像是边缘场景。
@dudewad:Angular 1.4 可能会更好。来自 AngularJS 1.4.0 的博客:“ngOptions 被完全重构以允许修复许多烦人的错误,”
哈哈“烦人的错误”。好的。好吧,在交货前 3 天升级时,我仍然有点小气,所以我现在会继续使用您的解决方案,这似乎工作得很好。不过,请注意未来 :) 谢谢!【参考方案4】:
可能对某人有用:
如果你想使用普通选项而不是 ng-options,你可以这样做:
<select ng-model="sortorder" ng-init="sortorder='publish_date'">
<option value="publish_date">Ascending</option>
<option value="-publish_date">Descending</option>
</select>
设置模型内联。使用 ng-init 去掉空选项
【讨论】:
我无法找到使用 OBJECTS 而不是 JSON 数组设置 ng-options 的明确示例,当我尝试在两者之间“翻译”时,不仅没有出现对,但它“默默地”失败了,所以我不知道我做错了什么。我最终在选项标签中选择了普通的 ng-repeat。我知道这不是最佳实践,但至少它有效。如果有人能指出我使用带有数据对象(不是 JSON)的 ng-options 的简单、易于交换的细节、对 angular-n00b 友好的 WORKING 示例,我会很高兴。如果它也使用 ng-init,那就双倍高兴。 我使用的是普通选项,但在控制器中我似乎没有获得所选下拉列表的值。例如:我试过 alert($scope.sortorder.value);和警报($scope.sortorder);两者都给出未定义的。这里如何获取选中的值? 非常感谢您。我正要在控制器中写一个完全没用的对象,我不需要我只需要一个简单的选择。再次感谢你。【参考方案5】:类似的事情也发生在我身上,是由于升级到 Angular 1.5.ng-init
导致的,似乎在较新版本的 Angular 中被解析为 type。在较旧的 Angular 中,ng-init="myModelName=600"
将映射到值为“600”的选项,即<option value="600">First</option>
,但在 Angular 1.5 中它不会找到它,因为它似乎希望找到值为 600 的选项,即<option value=600>First</option>
。然后 Angular 会插入一个随机的第一项:
<option value="? number:600 ?"></option>
角度
<select ng-model="myModelName" ng-init="myModelName=600">
<option value="600">First</option>
<option value="700">Second</option>
</select>
角度 > 1.2
<select ng-model="myModelName" ng-init="myModelName='600'">
<option value="600">First</option>
<option value="700">Second</option>
</select>
【讨论】:
谢谢!在我的情况下,我不能使用 ng-init(没有默认值)所以我将我的模型转换为一个字符串并且它起作用了! 对我的应用程序生产问题非常有用。谢谢@Nabil Boag 这确实有效,但更好的选择是在option
中使用ng-value="600"
而不是value
。它会将其解析为一个数字,您不必像现在这样转换您的值:)
@Max 我尝试了很多高价值的答案,但在找到你的答案之前都没有奏效。谢谢。【参考方案6】:
在这里的众多答案中,我想我会重新发布对我有用并满足以下条件的所有的解决方案:
在 ng-model 为 falsy 时提供 占位符/提示(例如,“--select region--” w.value=""
)
当 ng-model 值为 falsy 并且用户打开选项下拉菜单时,会选择占位符(此处提到的其他解决方案会使第一个选项显示为已选中,这可能会产生误导)
允许用户取消选择一个有效值,本质上是再次选择 falsy/默认值
代码
<select name="market_vertical" ng-model="vc.viewData.market_vertical"
ng-options="opt as (opt | capitalizeFirst) for opt in vc.adminData.regions">
<option ng-selected="true" value="">select a market vertical</option>
</select>
src
原创问答 - https://***.com/a/32880941/1121919
【讨论】:
你的意思是如果默认是<option ng-selected="true" value="null">
?
我的意思是,如果 ng-model 值设置为 null,则在 select 上创建角度和空选项【参考方案7】:
快速解决方案:
select option:empty display:none
希望它可以帮助某人。理想情况下,选择的答案应该是方法,但如果不可能,那么应该作为补丁工作。
【讨论】:
根据我的测试,这只适用于 Chrome(最重要的是新的 Chrome)和 Firefox。 IE 和 Safari 中断。不了解opera和其他边缘浏览器。不管怎样,不幸的是,这不是一个好的解决方案。 我们应该在 @HVarma 这是一个 CSS 规则。将其放在样式表中或 中 @KK ***.com/questions/48355599/… 你能检查一下吗?【参考方案8】:是的,当 ng-model 属性未定义时,ng-model 将创建空选项值。如果我们将对象分配给 ng-model,我们可以避免这种情况
例子
角度编码
$scope.collections = [
name: 'Feature', value: 'feature' ,
name: 'Bug', value: 'bug' ,
name: 'Enhancement', value: 'enhancement'
];
$scope.selectedOption = $scope.collections[0];
<select class='form-control' data-ng-model='selectedOption' data-ng-options='item as item.name for item in collections'></select>
重要提示:
将 $scope.collections[0] 或 $scope.collections[1] 之类的数组对象分配给 ng-model,不要使用对象属性。如果您从服务器获取选择选项值,使用回调函数,将对象分配给 ng-model
Angular 文档中的注释
注意:ngModel 通过引用而不是值进行比较。这在绑定到对象数组时很重要。看一个例子http://jsfiddle.net/qWzTb/
我试了很多次终于找到了。
【讨论】:
【参考方案9】:虽然@pkozlowski.opensource 和@Mark 的答案都是正确的,但我想分享我稍微修改过的版本,我总是选择列表中的第一项,无论其值如何:
<select ng-options="option.value as option.name for option in typeOptions" ng-init="form.type=typeOptions[0].value">
</select>
【讨论】:
【参考方案10】:我使用的是 Angular 1.4x,我找到了这个例子,所以我使用 ng-init 来设置 select 中的初始值:
<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.id for item in items"></select>
【讨论】:
【参考方案11】:我遇到了同样的问题。如果您使用普通帖子发布角度形式,那么您将面临这个问题,因为角度不允许您以您使用的方式设置选项的值。如果您获得“form.type”的值,那么您将找到正确的值。你必须发布它自己的角度对象而不是表单发布。
【讨论】:
【参考方案12】:一个简单的解决方案是设置一个带有空白值的选项""
我发现这消除了额外的未定义选项。
【讨论】:
Doenst work @ 1.4.3,它只是在表单中添加了 2 个空选项【参考方案13】:好的,实际上答案很简单:当有一个 Angular 无法识别的选项时,它包括一个沉闷的选项。
你做错的是,当你使用 ng-options 时,它会读取一个对象,比如[ id: 10, name: test , id: 11, name: test2 ] right?
这是您的模型值需要将其评估为相等,假设您希望选择值为 10,您需要将模型设置为 id: 10, name: test
之类的值以选择 10,因此它不会创建垃圾。
希望它可以帮助大家理解,我尝试了很艰难:)
【讨论】:
【参考方案14】:这个解决方案对我有用:
<select ng-model="mymodel">
<option ng-value="''" style="display:none;" selected>Country</option>
<option value="US">USA</option>
</select>
【讨论】:
投反对票可能是因为将 CSS 应用于选项元素并不适用于所有浏览器。 我刚刚在 Chrome、FireFox、Safari 和 Edge 上进行了测试 - 一切正常。 @MMM“所有浏览器”包括 IE。很多用户仍然坚持使用 IE 10 和 11,这可能就是投票失败的原因。 Chrome、fF、Saf 和 Edge 并非“所有浏览器”。【参考方案15】:这对我有用
<select ng-init="basicProfile.casteId" ng-model="basicProfile.casteId" class="form-control">
<option value="0">Select Caste....</option>
<option data-ng-repeat="option in formCastes" value="option.id">option.casteName</option>
</select>
【讨论】:
只是将选项添加到列表中并留下空白,遗憾的是。【参考方案16】:这很好用
<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
<option style="display:none" value=""></option>
</select>
它的工作方式是,这提供了在选择某些内容之前显示的第一个选项,display:none
将其从下拉列表中删除,所以如果你愿意,你可以这样做
<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
<option style="display:none" value="">select an option...</option>
</select>
这将在选择之前为您提供select and option
,但一旦选择它就会消失,并且不会出现在下拉列表中。
【讨论】:
其实你并没有回答问题本身,更糟糕的是,你只是隐藏了元素。【参考方案17】:在你的控制器中试试这个,顺序相同:
$scope.typeOptions = [
name: 'Feature', value: 'feature' ,
name: 'Bug', value: 'bug' ,
name: 'Enhancement', value: 'enhancement'
];
$scope.form.type = $scope.typeOptions[0];
【讨论】:
我试过你的方法,但不幸的是我无法让它工作。你能看看这个小提琴吗? jsfiddle.net/5PdaX【参考方案18】:这里是修复:
对于像这样的示例数据:
financeRef.pageCount = [listCount:10,listName:modelStrings.COMMON_TEN_PAGE,
listCount:25,listName:modelStrings.COMMON_TWENTYFIVE_PAGE,
listCount:50,listName:modelStrings.COMMON_FIFTY_PAGE];
选择选项应该是这样的:-
<select ng-model="financeRef.financeLimit" ng-change="financeRef.updateRecords(1)"
class="perPageCount" ng-show="financeRef.showTable" ng-init="financeRef.financeLimit=10"
ng-options="value.listCount as value.listName for value in financeRef.pageCount"
></select>
重点是当我们将value.listCount
写为value.listName
时,它会自动填充value.listName
中的文本,但所选选项的值是value.listCount
,尽管我的值显示正常 0,1,2 ..等等!!!
在我的例子中,financeRef.financeLimit
实际上是在抓取value.listCount
,我可以在控制器中动态地进行操作。
【讨论】:
【参考方案19】:我想补充一点,如果初始值来自某个父元素或 1.5 组件的绑定,请确保传递了正确的类型。如果在绑定中使用@
,则传递的变量将是字符串,如果选项是例如。整数,然后将显示空选项。
要么正确解析 init 中的值,要么与 <
绑定而不是 @
(除非必要,否则不推荐用于性能)。
【讨论】:
【参考方案20】:简单的解决方案
<select ng-model='form.type' required><options>
<option ng-repeat="tp in typeOptions" ng-selected="
form.type==tp.value?true:false" value="tp.value">tp.name</option>
【讨论】:
【参考方案21】:当您无法控制选项时,使用 jQuery 解决方案
html:
<select id="selector" ng-select="selector" data-ng-init=init() >
...
</select>
js:
$scope.init = function ()
jQuery('#selector option:first').remove();
$scope.selector=jQuery('#selector option:first').val();
【讨论】:
Pascal,有人对你投了反对票,因为这是一个 jQuery 解决方案,而不是 AngularJs 这个问题被要求挖掘出更多的Angular...:-/【参考方案22】:如果你使用 ng-init 你的模型来解决这个问题:
<select ng-model="foo" ng-app ng-init="foo='2'">
【讨论】:
【参考方案23】:我有同样的问题, 我(删除了“ng-model”)改变了这个:
<select ng-model="mapayear" id="mapayear" name="mapayear" style=" display:inline-block !important; max-width: 20%;" class="form-control">
<option id="removable" hidden> Selecione u </option>
<option selected ng-repeat="x in anos" value=" x.ano "> x.ano
</option>
</select>
到这里:
<select id="mapayear" name="mapayear" style=" display:inline-block !important; max-width: 20%;" class="form-control">
<option id="removable" hidden> Selecione u </option>
<option selected ng-repeat="x in anos" value=" x.ano "> x.ano
</option>
</select>
现在它可以工作了,但在我的情况下,这是因为我从 ng.controller 中删除了该范围,检查你是否没有这样做。
【讨论】:
【参考方案24】:唯一对我有用的是在ng-options
中使用track by
,就像这样:
<select class="dropdown" ng-model="selectedUserTable" ng-options="option.Id as option.Name for option in userTables track by option.Id">
【讨论】:
如果我使用这个ng-option
获取数组的最后一个值,我想设置option
的select
的值。它没有解决:(【参考方案25】:
参考 angularjs 文档中的示例如何克服这些问题。
-
转到此文档链接here
查找'通过 ngModel 解析/格式化将选择绑定到非字符串值'
您可以在那里看到,名为“convertToNumber”的指令解决了问题。
它对我有用。也可以看看它是如何工作的here
【讨论】:
【参考方案26】:我们可以使用 CSS 来隐藏第一个选项,但是在 IE 10、11 中它不会起作用。最好的方法是使用 Jquery 删除元素。此解决方案适用于在 chrome 和 IE10 中测试的主要浏览器,11
此外,如果您使用 angular ,有时使用 setTimeout 也可以
$scope.RemoveFirstOptionElement = function (element)
setTimeout(function ()
$(element.children()[0]).remove();
, 0);
;
【讨论】:
以上是关于为啥 AngularJS 在选择中包含一个空选项?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Kotlin 数据类可以在 Gson 的不可空字段中包含空值?
在剑道的日期管道中包含变量值(动态格式):AngularJS
使用browserify时如何在AngularJS中包含jQuery?