0
votes

I am working on angularJS ng-options group by functionality.I want to know there is any way to only display group names and apter click on group name show the group content in select drop down menu.

$scope.testArry =  [
    {
        "name":"john", 
        "class":"Grade1"
    },{
        "name":"Ann", 
        "class":"Grade1"
    },{
        "name":"jery", 
        "class":"Grade2"
    },{
        "name":"joy", 
        "class":"Grade2"
    },{
        "name":"Pere", 
        "class":"Grade1"
    }];

<select class="form-control" name="operator" ng-model="student" 
    ng-options="student as student.name group by student.class for studentin testArray">
    <option value="">Please Select</option>
</select>

This is work and group according to class.I want to select menu only display class and when click on class name show the relevant student.

enter image description here

1
What you want to do is already provided by Select2. Check out some samples here.Hoa
As I mentioned in one of my comments, what you want to do will create bad user experience. Create 10 classes, each class has 20 students then select a student at the end of the list and you know what I mean.Hoa
@Hora I know that too many clicks is bad UX, but user request it , that's why I try to implementDushyantha
If so, as a software developer, you should explain to your client why such an implementation is not good. And it doesn't just require more clicks, you'll have a very long select box when the number of classes and students grows. A user will have to scroll down the page to select a student.Hoa

1 Answers

1
votes

It is a complex case, but I found the solution:

I assume you can have structure like this:

        [{
           name: "Group 1",
           options: [
             {caption: "Option 1", value: "1"}, 
             {caption: "Option 2", value: "2"}
           ]
        }, {
           name: "Group 2",
           options: [
             {caption: "Option 3", value: "3"}, 
             {caption: "Option 4", value: "4"}
           ]
         }
        ]

But it's not ready for select component, because we cant bind ng-click on or tags and also we need proper order. Updated options array:

  [
     {
      "caption":"Group 1",
      "type":"group",
      "isActive":true,
      "parentGroupSelected":false
     },
     {
      "caption":"Option 1",
      "value":"1",
      "type":"option",
      "parentGroupSelected":false,
      "parentGroup":"Group 1"
     },
     {
      "caption":"Option 2",
      "value":"2",
      "type":"option",
      "parentGroupSelected":false,
      "parentGroup":"Group 1"},
     {
      "caption":"Group 2",
      "type":"group",
      "isActive":true,
      "parentGroupSelected":false
     },
     {
      "caption":"Option 3",
      "value":"3",
      "type":"option",
      "parentGroupSelected":true,
      "parentGroup":"Group 2"
     },
     {
      "caption":"Option 4",
      "value":"4",
      "type":"option",
      "parentGroupSelected":true,
      "parentGroup":"Group 2"
     }]

Template (HMTL)

    <div data-ng-controller="AppController as vm">

    <select data-ng-model="vm.selectModel" data-ng-change="vm.handler(vm.selectModel)">

      <option ng-value="item" data-ng-if="vm.checkVisibility(item)" data-ng-repeat="item in vm.optionsInline track by $index" >
          <span>{{item.caption}}</span>
      </option>

    </select>
    </div>

We need two functions:

  1. Handle click event - actually we have to put it in onchange listener
  2. Check visibility of actual options

JS

Visibility check function:

 vm.checkVisibility = function(option) {

          if(option.type == 'group') {
                return true;
          }

          if(option.type == 'option') {
               if(option.parentGroupSelected == true) {
                   return true;
               }
          }

          return false;

        }

Onclick (Change) handler:

 vm.handler = function(option) {

             if(option.type == 'group') {

                  option.isActive = !option.isActive;

                  vm.optionsInline.forEach(function(optionItem){

                  optionItem.parentGroupSelected = false; // accordion mode

                      if(optionItem.type == 'option') {

                          if(optionItem.parentGroup == option.caption) {
                               optionItem.parentGroupSelected = option.isActive;
                          }

                      }

                  })

             }
        }

If you still have questions you can refer to my jsfiddle example below

JSFiddle example