Hacking with Angular: 玩转ngOptions指令

更新于 2016-05-25  约 18 分钟

首先说说为什么要详细的了解一下这个指令,因为在工作中总是遇到关于下拉选项的一些操作,但是又常常会出现一些问题;基本会遇到下面一些问题:

  • 关于下拉框使用ng-repeat或者ng-options指令的区别

  • 关于下拉框的默认选项如何设置

  • 关于下拉框选项的model值如何绑定

  • 关于下拉框的禁用选项问题

  • 关于下拉框的分组问题

  • 关于下拉框的排序问题

下面我们就来好好的研究一下ng-options,下面的部分就是关于上面问题的解决方案。
关于下面的例子详见demo原文链接


下面的部分没有太按照上面的问题的顺序,但是他们的解决方法都在里面有提及。

下拉框的默认选项一般是可以通过使用ng-init指令或者在控制器中对selectmodel值进行赋值来达到这个目的的。
关于使用ng-repeat还是ng-options的选择,当我们的下拉列表循环的只是一些简单的字符串或者数字的时候,使用这两个指令都是可以的;但是当我们下拉列表循环的是一些比较复杂的数据并且还有一些附带的其它要求的时候,我们应该使用ng-options

  • 使用select结合ng-repeat指令组成一个含有默认值的下拉列表。

    • HTML部分

      <select ng-init="vm.item1 = vm.items1[0]"
              ng-model="vm.item1">
          <option ng-selected="v == vm.items1[0]"
                  value="{{v}}"
                  ng-repeat="v in vm.items1">
              {{v}}
          </option>
      </select>
    • JavaScript部分

      vm.items1 = [
                '选项一',
                '选项二',
                '选项三'
            ];

      我们使用ng-repeat指令对下拉列表的值进行循环,然后使用ng-initselectmodel进行初始化。

  • 使用ng-options达到和上面一样的效果

    • HTML部分

         <select ng-model="vm.item2"
                 ng-init="vm.item2 = vm.items2[0]"
                 ng-options="v for v in vm.items2">
        </select>
    • JavaScript部分

      vm.items2 = [1,2,3];

      下面的部分具体的讲解ng-options指令后面使用的复杂的表达式,还需要注意的是,我们使用的是数组作为下拉列表的输出,当然也可以使用对象,详情可以参考官网

  • select as label for value in array

    • 首先说明一下上面的表达式中每一项表示的是什么;array表示的是我们要进行循环的对象数组,
      value表示这个数组中的单独一项,也就是一个单独的对象,selectlabel都是对象中的某一个属性,其中select还可以表示整个对象;label表示的是下拉框中的显示的选项,select表示下拉框中选中某一个label之后下拉框的model的值。通俗一点说就是,label只是下拉框中表现出来让你选择的选项,而select是你选中那个选项之后,下拉列表的值

    • HTML部分

      <select ng-init="vm.item3 = vm.items3[0].value"
          ng-options="v.value as v.name for v in vm.items3"
          ng-model="vm.item3">
      </select>
    • JavaScript部分

          vm.items3 = [
              {name: '选项一', value: 1},
              {name: '选项二', value: 2},
              {name: '选项三', value: 3}
          ];
    • 解释一下上面的一些内容,其中ng-model="vm.item3"指定了这个下拉框的model值,我们使用ng-init进行下拉框的初始化ng-init="vm.item3 = vm.items3[0].value",关于ng-options="v.value as v.name for v in vm.items3"我们来看一下,其中v表示数组中的单个对象,as左边的值是我们的下拉框选中时的值,as右边的值是下拉框表面表示选择项。在这个例子中,我们会看到下拉框给我们的选项是选项一选项二选项三,但是当我们选中选项一的时候实际上下拉框的值是1也就是v.value

  • label group by group for value in array

    • group by group的解释,其中前面的group by是固定的,后面的group使我们分组的依据。

    • HTML部分

      <select ng-init="vm.item4 = vm.items4[0]"
                    ng-options="v.name group by v.group for v in vm.items4"
                    ng-model="vm.item4">
       </select>
    • JavaScript部分

      vm.items4 = [
               {name: '选项一', value: 1, group: 'A'},
               {name: '选项二', value: 2, group: 'A'},
               {name: '选项三', value: 3, group: 'A'},
               {name: '选项四', value: 4, group: 'B'},
               {name: '选项五', value: 5, group: 'B'},
               {name: '选项六', value: 6, group: 'C'},
               {name: '选项七', value: 7, group: 'C'}
           ];
    • 页面中的表现如下图:
      0_1464080997907_1-1.pic.jpg 关于上面代码的一些解释,可以从上图看到,只要我们把分组的信息写好,angular会帮助我们处理好分组的事情。

  • select as label disable when disable for value in array

    • disabled when disableddisabled when是固定的语句,后面的disabled是一个条件,如果条件是true的话,那么这一项是不可以被选中的。

    • HTML部分

      <select ng-init="vm.item5 = vm.items5[0].value"
                    ng-options="v.value as v.name disable when v.show for v in vm.items5"
                    ng-model="vm.item5">
       </select>
    • JavaScript部分

      vm.items5 = [
                {name: '选项一', value: 1},
                {name: '选项二', value: 2, show: true},
                {name: '选项三', value: 3},
                {name: '选项四', value: 4, show: true},
                {name: '选项五', value: 5}
            ];
    • 页面中的表现如下:
      0_1464081798225_1-2.pic.jpg 可以看到,选项二和选项四是禁用的。

  • label disable when disable for value in array

    • HTML部分

              <select ng-init="vm.item6 = vm.items6[0]"
                            ng-options="v.name disable when v.show for v in vm.items6"
                            ng-model="vm.item6">
               </select>
    • JavaScript部分

      vm.items6 = [
               {name: '选项一', value: 1},
               {name: '选项二', value: 2, show: true},
               {name: '选项三', value: 3},
               {name: '选项四', value: 4, show: true},
               {name: '选项五', value: 5}
           ];
    • 这个例子和上面的很相似,但是还是有一些区别的;这个例子的下拉框的model值是一个对象,上面那个例子的下拉框的model只是一个数字;从哪里可以看出来呢?因为两个ng-options指令后面的表达式是不一样的,如果表达式中使用了as关键字的话那么as左边的表达式的值就是我们的下拉框的model值,如果不使用的话,默认的就是我们数组中的某一项的值,在此处是一个对象。

  • label for value in array track by trackexpr

    • track by是用来识别数组中的每个对象的,当这个数组再次被重新创建或者更新的时候的时候,已经选择的选项会被保留下来,也就是说,会保留每一项当时选择的状态

    • HTML部分(未使用track by)

                <select multiple
                        ng-init="vm.item7 = []"
                        ng-options="v.name for v in vm.items7"
                        ng-model="vm.item7">
                </select>
    • JavaScript部分(未使用track by)

      vm.items7 = [
                {name: '选项一', value: 1, id: 1},
                {name: '选项二', value: 2, id: 2},
                {name: '选项三', value: 3, id: 3},
                {name: '选项四', value: 4, id: 4},
                {name: '选项五', value: 5, id: 5}
            ];
    • JavaScript部分,公用的函数changeItems部分

           function changeItems() {
                vm.items7 = [
                    {name: '选项一', value: 1, id: 1},
                    {name: '选项二', value: 2, id: 2},
                    {name: '选项三', value: 3, id: 3},
                    {name: '选项四', value: 4, id: 4},
                    {name: '选项五', value: 5, id: 5},
                    {name: '选项6', value: 6, id: 6}
                ];
                vm.items8 = [
                    {name: '选项一', value: 1, id: 1},
                    {name: '选项二', value: 2, id: 2},
                    {name: '选项三', value: 3, id: 3},
                    {name: '选项四', value: 4, id: 4},
                    {name: '选项五', value: 5, id: 5},
                    {name: '选项6', value: 6, id: 6}
                ];
            }
    • HTML部分

                <select multiple
                        ng-init="vm.item8 = []"
                        ng-options="v.name for v in vm.items8 track by v.id"
                        ng-model="vm.item8">
                </select>
    • JavaScript部分

      vm.items8 = [
                {name: '选项一', value: 1, id: 1},
                {name: '选项二', value: 2, id: 2},
                {name: '选项三', value: 3, id: 3},
                {name: '选项四', value: 4, id: 4},
                {name: '选项五', value: 5, id: 5}
            ];
    • 我们使用了下拉框的多选模式,这样就可以更清楚地看到我们说的为什么要使用track by这个关键字的原因,在demo7中,我们没有使用track by,我们将demo7下拉框的model值初始化为一个数组,并且有一个辅助的函数changeItems,模拟下拉框的选项变化;当我们选中一些选项后,点击更新按钮,会发现之前的选择已经被清零了;当是当我们使用了track by之后,就像demo8中的示例那样,当我们选中了一些选项之后,再次点击更新按钮,会发现之前选择的选项依旧还是存在的。

  • label for value in array | orderBy : expr track by trackexpr

    • 我们也可以在后面的表达式语句中使用orderBy过滤器,使用过滤器的好处是,让下拉框的选项按照我们的要求进行进行排列,让我们使用起来更加方便。

    • HTML部分

              <select ng-init="vm.item9 = vm.items9[vm.items9.length - 1]"
                      ng-options="v.name for v in vm.items9 | orderBy: ['value'] track by v.id"
                      ng-model="vm.item9">
              </select>
    • JavaScript部分

       vm.items9 = [
              {name: '选项一', value: 5, id: 1},
              {name: '选项二', value: 4, id: 2},
              {name: '选项三', value: 3, id: 3},
              {name: '选项四', value: 2, id: 4},
              {name: '选项五', value: 1, id: 5}
          ];
    • 首先我们的数据部分和上面的不一样,我们将数据中的value部分进行了倒序,然后又在表达式中使用orderBy过滤器,并且按照value值进行排序;关于orderBy过滤器的使用方法可以参考官网。还要注意的是,我们也给这个下拉框的model初始化了一个值,不然这个下拉框会有一个空白的选项,给用户的的体验很不好;当然我们也是根据数据的特征使用了ng-init="vm.item9 = vm.items9[vm.items9.length - 1]"进行初始化。

关于下拉框要循环的是对象的情况基本上和上面的差不多,大家可以自行看官网上的说明,好了就先到这里了。

阅读 6.3k更新于 2016-05-25

推荐阅读
技术风暴
用户专栏

Classical is something not fade,but grow more precious with time pass by,so is dream id dream.

189 人关注
33 篇文章
专栏主页
目录