为啥 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 是您的值之一,这将不起作用。 是否可以在空的&lt;option&gt; 中添加一个文本,所以 tat angular 生成了类似&lt;option value="?"&gt;Select an option&lt;/option&gt; 的内容 @Tareck117 只是写&lt;option value=""&gt;Select an option&lt;/option&gt; 那是选项列表的空值。不需要 ?-字符。【参考方案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" 放入选择属性,您可以看到没有选择任何内容!就像在默认的 &lt;select&gt;-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”的选项,即&lt;option value="600"&gt;First&lt;/option&gt;,但在 Angular 1.5 中它不会找到它,因为它似乎希望找到值为 600 的选项,即&lt;option value=600&gt;First&lt;/option&gt;。然后 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

【讨论】:

你的意思是如果默认是&lt;option ng-selected="true" value="null"&gt; 我的意思是,如果 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 中的值,要么与 &lt; 绑定而不是 @(除非必要,否则不推荐用于性能)。

【讨论】:

【参考方案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 获取数组的最后一个值,我想设置optionselect 的值。它没有解决:(【参考方案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?

如何在 angularjs 控制器中包含现有的 javascript 列表

如何在您的 Ionic / AngularJs 应用程序中包含和使用节点模块?