Keep md-select open until clicked outside - AngularJS

1.3k Views Asked by At

I am using md-select rendering md-checkbox wiyth a selectAll option.

If I select all, all checkboxes are selected and the dropdown closes which is expected.

How do I trigger not to close the dropdown when any value other than All is selected and close it on outside click?

var app = angular.module('BlankApp', ['ngMaterial', 'ngMessages']);

app.controller('mdSelectController', function($scope, $mdPanel, $mdSidenav, $mdDialog) {

  $scope.helpers = [{
      name: 'All',
      selected: false
    },
    {
      name: 'Ron',
      selected: false
    },
    {
      name: 'Jim',
      selected: false
    },
    {
      name: 'John',
      selected: false
    },
    {
      name: 'Paul',
      selected: false
    },
    {
      name: 'Jeremie',
      selected: false
    }
  ];

  $scope.changeCheckbox = function(rating) {
  console.log(rating)
    if (rating.name === 'All' && rating.selected === true) {
      _.forEach($scope.helpers, function(item) {
        item.selected = true;
      });
    }
    if (rating.name === 'All' && rating.selected === false) {
      _.forEach($scope.helpers, function(item) {
        item.selected = false;
      });
    }
    if (rating.name !== 'All') {
      console.log("Not all");
      _.forEach($scope.helpers, function(item) {
        if (item.name === 'All') {
          item.selected = false;
        }
      });
    }
  };

});
<html lang="en">

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Angular Material style sheet -->
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.css">
</head>

<body ng-app="BlankApp" ng-controller="mdSelectController" ng-cloak>
  <!--
    Your HTML content here
  -->

  <!-- Angular Material requires Angular.js Libraries -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-aria.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-messages.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

  <!-- Angular Material Library -->
  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.js">
  </script>
  <md-input-container>
    <label>Rating</label>
    <md-select id="ratingDropdown" ng-model="automationRatingObj" md-container-class="ratingDropdown" required="required">
      <md-option ng-value="rating" ng-repeat="rating in helpers track by $index">
        <md-checkbox ng-model="rating.selected" aria-label="Select a Rating" ng-change="changeCheckbox(rating)"></md-checkbox>{{rating.name}}
      </md-option>
    </md-select>
  </md-input-container>

</body>

</html>

Please advice. I checked the API of md-select but they dont have any code to keep the dropdown open. Also, how do I disable click on the text inside md-select and enable click only for checkbox?

2

There are 2 best solutions below

2
On BEST ANSWER

You want the dropdown to close when clicking all, but to remain open when clicking any other item. You can check for which value you are at in ng-repeat and add $event.stopPropagation(); to all objects without 'All'. You can do this using ternary operator on ng-click on md-option: ng-click="rating.name != 'All' ? $event.stopPropagation(): ''"

var app = angular.module('BlankApp', ['ngMaterial', 'ngMessages']);

app.controller('mdSelectController', function($scope, $mdPanel, $mdSidenav, $mdDialog) {

  $scope.helpers = [{
      name: 'All',
      selected: false
    },
    {
      name: 'Ron',
      selected: false
    },
    {
      name: 'Jim',
      selected: false
    },
    {
      name: 'John',
      selected: false
    },
    {
      name: 'Paul',
      selected: false
    },
    {
      name: 'Jeremie',
      selected: false
    }
  ];

  $scope.changeCheckbox = function(rating) {
  console.log(rating)
    if (rating.name === 'All' && rating.selected === true) {
      _.forEach($scope.helpers, function(item) {
        item.selected = true;
      });
    }
    if (rating.name === 'All' && rating.selected === false) {
      _.forEach($scope.helpers, function(item) {
        item.selected = false;
      });
    }
    if (rating.name !== 'All') {
      console.log("Not all");
      _.forEach($scope.helpers, function(item) {
        if (item.name === 'All') {
          item.selected = false;
        }
      });
    }
  };

});
<html lang="en">

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Angular Material style sheet -->
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.css">
</head>

<body ng-app="BlankApp" ng-controller="mdSelectController" ng-cloak>
  <!--
    Your HTML content here
  -->

  <!-- Angular Material requires Angular.js Libraries -->
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-aria.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-messages.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

  <!-- Angular Material Library -->
  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.8/angular-material.min.js">
  </script>
  <md-input-container>
    <label>Rating</label>
    <md-select id="ratingDropdown" ng-model="automationRatingObj" md-container-class="ratingDropdown" required="required">
      <md-option ng-value="rating" ng-repeat="rating in helpers track by $index" ng-click="rating.name != 'All' ? $event.stopPropagation(): ''" >
        <md-checkbox ng-model="rating.selected" aria-label="Select a Rating" ng-change="changeCheckbox(rating)"></md-checkbox>{{rating.name}}
      </md-option>
    </md-select>
  </md-input-container>

</body>

</html>

3
On

You can use multiple from md-select instead of using md-checkbox. But you need update changeCheckbox function - for select ALL.

Something like this:

<md-select id="ratingDropdown" ng-model="automationRatingObj" md-container-class="ratingDropdown" required="required" multiple="true" ng-change="changeCheckbox()">
      <md-option ng-value="rating" ng-repeat="rating in helpers track by $index" >
        {{rating.name}}
      </md-option>
    </md-select>