【问题标题】:AngularJS - value attribute for selectAngularJS - 选择的值属性
【发布时间】:2012-11-28 00:38:19
【问题描述】:

源 JSON 数据为:

[
  {"name":"Alabama","code":"AL"},
  {"name":"Alaska","code":"AK"},
  {"name":"American Samoa","code":"AS"},
  ...
]

我试试

ng-options="i.code as i.name for i in regions"

但我得到了:

<option value="?" selected="selected"></option>
<option value="0">Alabama</option>
<option value="1">Alaska</option>
<option value="2">American Samoa</option>

虽然我期望得到:

<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AS">American Samoa</option>

那么,如何获取值属性并去掉“?”项目?

顺便说一句,如果我将 $scope.regions 设置为静态 JSON 而不是 AJAX 请求的结果,则空项会消失。

【问题讨论】:

标签: select angularjs options


【解决方案1】:

除非您自己在 ng-repeat 中构建它们,否则您无法真正做到这一点。

<select ng-model="foo">
   <option ng-repeat="item in items" value="{{item.code}}">{{item.name}}</option>
</select>

但是……这可能不值得。最好让它按设计运行,让 Angular 处理内部工作。 Angular 以这种方式使用索引,因此您实际上可以将整个对象用作值。因此,您可以使用下拉绑定来选择整个值而不仅仅是一个字符串,这非常棒:

<select ng-model="foo" ng-options="item as item.name for item in items"></select>

{{foo | json}}

【讨论】:

  • 虽然您的第一个示例生成了一个工作/正确的选择列表,并且您警告不要使用它,但请注意它不适用于 Angular 的其余部分。例如,这不会按预期工作:select AK。一般来说,value 属性可能不应该与 Angular 的 select 指令一起使用。
  • 这是解决关于track byselect 无法协同工作的长期错误的绝妙方法。有关错误报告,请参见此处:github.com/angular/angular.js/issues/6564
【解决方案2】:

如果为下拉列表指定的模型不存在,则 Angular 将生成一个空选项元素。因此,您必须像这样在选择上明确指定模型:

<select ng-model="regions[index]" ng-options="....">

参考以下,因为之前已经回答过:

Why does AngularJS include an empty option in select? 和这个fiddle

更新:试试这个:

<select ng-model="regions[index].code" ng-options="i.code as i.name for i in regions">
</select>

or

<select ng-model="regions[2]" ng-options="r.name for r in regions">
</select>

请注意,选择中没有空选项元素。

【讨论】:

    【解决方案3】:

    您可以将模型修改为如下所示:

    $scope.options = {
        "AL" : "Alabama",
        "AK" : "Alaska",
        "AS" : "American Samoa"
      };
    

    然后使用

    <select ng-options="k as v for (k,v) in options"></select>
    

    【讨论】:

    • 此变体不起作用。它根据顺序生成具有相同数值和文本的选项或具有数值和空文本的选项:“k as v”或“v as k”
    【解决方案4】:

    您首先尝试的应该可以,但 HTML 不是我们所期望的。我添加了一个选项来处理最初的“未选择项目”情况:

    <select ng-options="region.code as region.name for region in regions" ng-model="region">
       <option style="display:none" value="">select a region</option>
    </select>
    <br>selected: {{region}}
    

    上面生成了这个 HTML:

    <select ng-options="..." ng-model="region" class="...">
       <option style="display:none" value class>select a region</option>
       <option value="0">Alabama</option>
       <option value="1">Alaska</option>
       <option value="2">American Samoa</option>
    </select>
    

    Fiddle

    即使 Angular 使用数字整数作为值,模型(即 $scope.region)也会根据需要设置为 AL、AK 或 AS。 (当从列表中选择一个选项时,Angular 使用数值来查找正确的数组条目。)

    在第一次了解 Angular 如何实现其“选择”指令时,这可能会让人感到困惑。

    【讨论】:

    • 我发现 HTML 没有反映范围内设置的值很混乱,而且缺乏透明度...
    • 这是一种不同的思维方式。您实际上选择的是region object,而不是region.code string。一旦用户选择了某些东西,region object 将被选中。然后,当您稍后需要代码时,只需访问region.code。希望对您有所帮助。
    • 有人能解释一下语法“region.code as region.name”实际上是“说”什么......这对我来说似乎没有什么意义。那个“as”关键字完全把我扔了,因为我认为它在推断任何类型的含义方面没有语法用途。
    • @ProxyTech,我是这样想的:使用 region.code 作为要分配给模型的值,但向用户显示 region.name。 API docs 将 region.name 部分称为label
    • @MarkRajcok 这是我的 C# 范式,导致与用于从类型转换为另一个类型的“as”关键字混淆。然后是我的“英语语言”范式,其中关键字“as”表示“region.came”正在交互/取代“region.code”......在上下文中完全不是这种情况。在我看来只是非常糟糕的语法。
    【解决方案5】:

    似乎不可能以任何有意义的方式实际使用 select 的“值”作为普通的 HTML 表单元素,并且还可以通过 ng-options 以批准的方式将其连接到 Angular。作为妥协,我最终不得不在我的选择旁边放置一个隐藏的输入,并让它跟踪与我的选择相同的模型,就像这样(为了简洁起见,所有这些都非常简化了真实的生产代码):

    HTML:

    <select ng-model="profile" ng-options="o.id as o.name for o in profiles" name="something_i_dont_care_about">
    </select>
    <input name="profile_id" type="text" style="margin-left:-10000px;" ng-model="profile"/>
    

    Javascript:

    App.controller('ConnectCtrl',function ConnectCtrl($scope) {
    $scope.profiles = [{id:'xyz', name:'a profile'},{id:'abc', name:'another profile'}];
    $scope.profile = -1;
    }
    

    然后,在我的服务器端代码中,我只查找了params[:profile_id](这恰好是一个 Rails 应用程序,但同样的原则适用于任何地方)。因为隐藏的输入与选择跟踪相同的模型,所以它们会自动保持同步(不需要额外的 javascript)。这是 Angular 最酷的部分。它几乎弥补了它对 value 属性所做的副作用。

    有趣的是,我发现这种技术只适用于未隐藏的输入标签(这就是为什么我必须使用 margin-left:-10000px; 将输入移出页面的技巧)。这两种变体不起作用:

    <input name="profile_id" type="text" style="display:none;" ng-model="profile"/>
    

    <input name="profile_id" type="hidden" ng-model="profile"/>
    

    我觉得这一定意味着我错过了一些东西。 Angular 的问题似乎太奇怪了。

    【讨论】:

    • 您也可以使用&lt;input name="profile_id" type="hidden" value="{{profile}}"/&gt;。它有效。
    【解决方案6】:

    如果您使用track by 选项,则value 属性写入正确,例如:

    <div ng-init="a = [{label: 'one', value: 15}, {label: 'two', value: 20}]">
        <select ng-model="foo" ng-options="x for x in a track by x.value"/>
    </div>
    

    产生:

    <select>
        <option value="" selected="selected"></option>
        <option value="15">one</option>
        <option value="20">two</option>
    </select>
    

    【讨论】:

    • 这在 Angular 1.3 kittyminky 中完美运行,请检查您的语法。 - 这应该是选择的答案。
    【解决方案7】:

    你可以使用

    state.name for state in states track by state.code
    

    其中states在JSON数组中,state是数组中每个对象的变量名。

    希望对你有帮助

    【讨论】:

      【解决方案8】:

      尝试如下:

      var scope = $(this).scope();
      alert(JSON.stringify(scope.model.options[$('#selOptions').val()].value));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-19
        • 2013-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多