1

I'm retrieving some data from a rest service and use it to populate the options in a select with AngularJS.

If the user opens the select after the data has been retrieved, there is no problem.

If the user opens the select before the data is retrieved, and keeps it opened until the options are populated, then chrome doesn't resize the list of options and just shows a scrollbar whith height one line. This is unconfortable and misleading to the user.

Is there some way to fix this in Chrome? I realize that I could keep the select disabled or hidden until I populate the options, but I want to know if there is some other alternative.

Html (the button simulates the call to a rest service):

<div ng-controller="MyCtrl">
  <button type="button" ng-click="clickButton()">Add options
  </button>
  <select ng-model="value" style="width: 200px;"
    ng-options="o.id as o.label for o in list"
  ><option value=""></option></select>
  {{value}}
</div>

Javascript:

function MyCtrl($scope, $timeout) {
    $scope.list = [];
    function addToList() {
        $scope.list = [{
            "id" : 1,
            "label" : "One"
          }, {
            "id" : 2,
            "label" : "Two"
          }, {
            "id" : 3,
            "label" : "Three"
          }
        ];
    }
    $scope.clickButton = function() {
        $timeout(function() {
        addToList();
      }, 5000);
    };
}

In jsFiddle: http://jsfiddle.net/PabloMG/u3fz9be0/

Pablo
  • 3,655
  • 2
  • 30
  • 44
  • I think your best bet would be to add a condition to your select input: – Rob Apr 14 '16 at 15:23
  • Created a fiddle: https://jsfiddle.net/y7g3y9st/ The timeout is just used for a proof of concept. – Rob Apr 14 '16 at 15:27

2 Answers2

2

I'm always a fan of using ng-if as you can add a loading message before the data gets added. This is more explicit to what's going on rather than a disabled input.

Note, the timeout here is being used for a proof of concept. You probably want to load your list from an $http callback in your controller.

UPDATE: Added second select input using ng-disabled

Fiddle: https://jsfiddle.net/y7g3y9st/

function ListCtrl($timeout) {
  var vm = this;
  vm.list = [];

  loadList();

  function loadList() {
    $timeout(function() {
      vm.list = [{
        "id": 1,
        "label": "One"
      }, {
        "id": 2,
        "label": "Two"
      }, {
        "id": 3,
        "label": "Three"
      }]
    }, 2000);
  }
}

<div ng-if="!ctrl.list.length">
 Loading list...
</div>
<select ng-model="value" style="width: 200px;" ng-options="o.id as o.label for o in ctrl.list" ng-if="ctrl.list.length">
 <option value=""></option>
</select>

<!-- ng-disabled -->
<select ng-model="value" style="width: 200px;" ng-options="o.id as o.label for o in ctrl.list" ng-disabled="!ctrl.list.length">
  <option value=""></option>
</select>
Rob
  • 1,840
  • 2
  • 12
  • 19
1

I've run into a similar situation before where we blurred the select box, waited until the options were appended, and then gave focus to the select box again. It was a bit weird if you already had it open to see it close, but it was better than sitting there with an open select box that had no data in it.

Your particular example code would be really odd as you're forcing a 5 second wait.

This will show the basic functionality.

$scope.clickButton = function() {
    $timeout(function() {
    addToList();
    document.querySelector('select').blur();
    document.querySelector('select').focus();
  }, 5000);

In our implementation we checked to see if the particular select box had focus before we blurred it, and only gave it focus again if the box was focused when we blurred it initially.

Jeff
  • 4,136
  • 23
  • 32
  • demo: http://jsfiddle.net/u3fz9be0/4/ -- this question is also relevant: http://stackoverflow.com/questions/19652085/open-dropdown-list-from-javascript-function – Aust Apr 14 '16 at 15:42
  • Oh, nice...you even opened it again. – Jeff Apr 14 '16 at 15:50
  • Another way to do this would be using the ng-disabled directive on the select input like the second select in this example: https://jsfiddle.net/y7g3y9st/ I would prefer this over mixing document selectors in the controller. – Rob Apr 14 '16 at 15:54
  • I'm going to accept this answer since it also works if you are updating the list of options and don't want to disable it everytime that you have to update it. The other answer is also useful most of the time, so I upvoted it. – Pablo Apr 20 '16 at 11:01