为什么AngularJS在select中包含一个空选项?


652

在过去的几周中,我一直在使用AngularJS,而让我感到困扰的一件事是,即使尝试了所有置换或http://docs.angularjs.org/api/ng规范中定义的配置,.directive:select,我仍然得到一个空选项作为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>

我需要怎么做才能摆脱它?

PS:事情也不需要这样做,但是如果您使用select2而不进行多重选择,那看起来就很奇怪。

Answers:


646

optionng-model传递给的一组选项中不存在被引用的值时,将生成空值ng-options。这样做是为了防止意外选择模型:AngularJS可以看到初始模型要么未定义,要么不在选项集中,并且不想自己决定模型的值。

如果要摆脱空选项,只需在控制器中选择一个初始值,例如:

$scope.form.type = $scope.typeOptions[0].value;

这是jsFiddle:http : //jsfiddle.net/MTfRD/3/

简而言之:空选项意味着没有选择有效的模型(有效的意思是:从选项集中)。您需要选择一个有效的模型值来摆脱此空选项。


7
我尝试了$ scope.form.type =''; 和$ scope.form.type = $ scope.typeOptions [0],但是我还是这样-<option value =“?” selected =“ selected”> </ option>
Sudhanshu 2012年

5
有时在JS中包含这些数据确实没有任何意义。如果是由服务器决定该选择内容是什么,那么JS为什么要重复它呢?
heneryville

11
不幸的是,如果您使用数组,null则此方法无效,它是您的值之一。
vpiTriumph

6
是否有可能在空的文本<option><option value="?">Select an option</option>
框中

3
@ Tareck117只是说那是选项列表<option value="">Select an option</option>的空值。不需要?字符。
塞巴斯蒂安

235

如果需要初始值,请参见@ pkozlowski.opensource的答案,也可以使用ng-init在视图中(而不是在控制器中)实现该FYI:

<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>

4
@hugo,正在工作的小提琴:jsfiddle.net/4qKyx/1 请注意,显示了“选择一种类型”,但是没有与之关联的值。一旦选择了其他内容,您将不会再看到它。(在Chrome上测试。)
Mark Rajcok

1
@MarkRajcok-极好的建议!我偶然发现了另一个例子,您的示例带有transclusion指令。你能看看吗?plnkr.co/edit/efaZdEQlNfoDihk1R1zc?p=preview
Jan-

2
问题是您仍然可以使用键盘进行选择,请参阅stackoverflow.com/a/8442831/57344解决方案
HaveAGuess 2014年

2
这可能暂时可行
Ed Norris

3
在IE10中不起作用,“选择类型”始终可见并且可以选择。
罗宾2014年

121

角度<1.4

对于在那里将“ 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选择器选择为“实际”选项,而不是隐藏的选项。当您使用量角器进行端到端测试并且(无论出于何种原因)使用by.css()定位选择选项时,此功能将非常有用。

角> = 1.4

由于select和options指令的重构,using ng-if不再是一个可行的选项,因此您必须转向ng-show="false"使其重新工作。


5
应该是可接受的答案,因为这是所选内容的正确视觉行为。您将size="5"selects属性放入,可以看到没有选择任何内容!就像在默认的<select>-Element中一样!我不明白为什么angular会为没有multiple属性的选择做这种事情...
Sebastian

1
是的,我同意,这应该是公认的答案。这就是“成角度的方式”。ng-if实际上从dom中删除了options元素(当为false时),因此该解决方案也适用于所有没有“ hacky”编码(与ng-hide或ng-show相反)的浏览器。
Sander_P 2015年

2
按我的定义,@ Sander_P认为此解决方案是“ hacky”编码(使dom中的某些内容诱使角度将其取出),但您是对的,它仍然是“最佳”解决方案。“甚至更好”的解决方案是允许毫无价值的选择!有没有搞错?它不像这是一个边缘场景。
dudewad

@dudewad:Angular 1.4可能会更好。来自1.4.0的AngularJS博客:“ ngOptions已完全重构,可以修复许多烦人的错误,”
Sander_P 2015年

1
哈哈“烦人的虫子”。好的。好吧,在交付前三天进行升级时,我还是有点不了解,所以我现在将继续为您提供解决方案,该方案似乎一直在运转。值得一提的是:)谢谢!
dudewad

36

可能对某人有用:

如果要使用普通选项而不是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。我知道这不是最佳做法,但至少可以奏效。如果有人可以指出一个简单易用的细节,可以使用ng-options和数据对象(NOT JSON)对angular-n00b友好的工作示例,我会很高兴。如果它也使用ng-init,则将其倍增。
代码寿司

我使用的是普通选项,但在控制器中,我似乎未获取所选下拉列表的值。例如:我尝试过alert($ scope.sortorder.value); 和警报($ scope.sortorder); 两者都给未定义。如何在此处获取所选值?
Maverick Riz

非常感谢你做的这些。我将要在控制器中编写一个完全没用的对象,而我只需要简单选择即可。再次感谢您。
穆罕默德·本·尤斯拉特

22

我也发生了类似的情况,这是由于将角度升级到1.5而引起的。ng-init似乎正在解析较新版本的Angular中的类型。在较旧的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>

角度<1.2.x

<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>

1
谢谢!在我的情况下,我不能使用ng-init(无默认值),因此我将模型转换为字符串,并且可以正常工作!
罗德里戈·格拉萨

对我的应用程序生产问题非常有用。感谢@Nabil Boag
Venki '17

3
这个作品,肯定的,但更好的选择是使用ng-value="600"option代替value。将其解析到一个号码,你不必须转换自己的价值观像你现在要做的:)
马克斯

@Max我尝试了很多高价值的答案,但直到找到您的答案都无济于事。谢谢。
安德鲁(Andrew)

21

在这里的众多答案中,我认为我会重新发布对我有用的解决方案,并满足以下所有条件:

  • 当ng模型错误时提供了一个占位符/提示(例如“ --select region--” w。)value=""
  • 当ng-model值错误并且用户打开选项下拉菜单时,将选择占位符(此处提到的其他解决方案会使第一个选项显示为选中状态,这可能会引起误解)
  • 允许用户取消选择有效值,本质上再次选择错误 /默认值

在此处输入图片说明

<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: //stackoverflow.com/a/32880941/1121919


您的意思是默认值是<option ng-selected="true" value="null">吗?
jusopi

我的意思是,如果ng-model值设置为null,则在选择时创建angular创建和空选项
Flezcano

16

快速解决方案:

select option:empty { display:none }

希望它可以帮助某人。理想情况下,选择的答案应该是方法,但如果无法解决,则应作为补丁。


2
根据我的测试,这仅适用于Chrome(最新一代的Chrome)和Firefox。IE和Safari中断。不了解Opera和其他边缘浏览器。无论哪种方式,不幸的是,这都不是一个好的解决方案。
dudewad

我们应该将其放置在<select>关闭之前的html中,还是放置在js中
H Varma

1
@HVarma这是CSS规则。将其放在样式表中或<style>标记中
KK


14

是,当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/

我尝试了很多次终于找到了。


8

尽管@ pkozlowski.opensource和@Mark的答案都是正确的,但我还是想分享一下我的稍作修改的版本,无论该值是多少,我总是在列表中选择第一项:

<select ng-options="option.value as option.name for option in typeOptions" ng-init="form.type=typeOptions[0].value">
</select>

4

我使用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>

3


我遇到了同样的问题。如果您要发布带有正常发布的角度表格,那么您将面临此问题,因为角度不允许您以已使用的方式设置选项的值。如果获得“ form.type”的值,则将找到正确的值。您必须将角度对象本身过帐而不是表格过帐。


3

一个简单的解决方案是将一个选项设置为空值,""我发现这消除了多余的未定义选项。


5
Doenst工作@ 1.4.3,它只向表单添加了2个空选项
Denny Mueller

3

好的,答案很简单:当某个选项未被Angular识别时,它就包含了一个沉闷的选项。您做错的是,当您使用ng-options时,它读取一个对象,说[{ id: 10, name: test }, { id: 11, name: test2 }] right?

这是您的模型值需要等于或等于10的值,例如,您希望选择的值为10,需要将模型设置为类似于{ id: 10, name: test }选择10 的值,因此不会创建该垃圾。

希望它能帮助大家理解,我在尝试时花了很多时间:)


2

此解决方案适用于我:

<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

@MMM“所有浏览器”都包含IE。许多用户仍然对IE 10和11感到困惑,这很可能是造成投票否决的原因。Chrome,fF,Saf和Edge并非“所有浏览器”。
PKD

1

这对我有用

<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>

可悲的是,只将选项添加到列表中并留下空白。
AMontpetit '16

1

这工作得很好

<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选择前的选择,但是一旦选择,它就会消失,并且不会显示在下拉菜单中。


实际上,您没有回答问题本身,更糟糕的是,您只是在隐藏元素。
Marco Marco

0

按照相同的顺序在您的控制器中尝试以下操作:

$scope.typeOptions = [
    { name: 'Feature', value: 'feature' }, 
    { name: 'Bug', value: 'bug' }, 
    { name: 'Enhancement', value: 'enhancement' }
];
$scope.form.type = $scope.typeOptions[0];

我尝试了您的方法,但不幸的是我无法使它起作用。你能看看这个小提琴吗?jsfiddle.net/5PdaX
Aniket Sinha

0

解决方法是:

对于像这样的样本数据:

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.listCountas时value.listName,它会自动填充文本,value.listName但所选选项value.listCount的值是我的值显示正常的0,1,2 ..等等!

就我而言,financeRef.financeLimit实际上是在抓取,value.listCount并且我可以在控制器中动态进行操作。


0

我想补充一点,如果初始值来自某个父元素或1.5组件的绑定,请确保传递正确的类型。如果@在绑定中使用,则传递的变量将为字符串,并且选项为例如。整数,则显示空选项。

要么正确解析init的值,要么与<而不是绑定@(除非有必要,否则建议不要这样做)。


0

简单的解决方案

<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>


0

当您无法控制选项时,可以使用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
Mawg说恢复Monica

询问问题以挖掘出更多的Angular ...:-/
Sahu V Kumar


0

我有同样的问题,我(已删除“ 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删除了该范围,请检查您是否没有这样做。



0

对我唯一有效的方法是使用track byin ng-options,如下所示:

 <select class="dropdown" ng-model="selectedUserTable" ng-options="option.Id as option.Name for option in userTables track by option.Id">


如果我用这个ng-option得到数组的最后一个值,我要的设定值optionselect。它没有解决:(
rufatZZ

0

请参阅angularjs文档中的示例,以解决这些问题。

  1. 在此处转到此文档链接
  2. 查找' 通过ngModel解析/格式化将选择绑定到非字符串值 '
  3. 在那可以看到,名为“ convertToNumber ”的指令解决了该问题。

这个对我有用。在这里也可以看到它的工作原理


0

我们可以使用CSS隐藏第一个选项,但是在IE 10、11中将无法使用。最好的方法是使用Jquery删除元素。该解决方案适用于在chrome和IE10中测试过的主要浏览器,11

另外,如果您使用angular,则有时使用setTimeout可以正常工作

$scope.RemoveFirstOptionElement = function (element) {
    setTimeout(function () {
        $(element.children()[0]).remove();
    }, 0);
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.