Alex Man
Alex Man

Reputation: 4886

space is shown when selecting the dropsdown option - angularjs

I have created an application in AngularJS with a drop down with space in option using a filter. The application is working fine with the options in drop down with indentation space before the values but the problem is when a select an option which is having a space, the space is also shown in the view like as shown below

enter image description here

actually I want the indentation space within the drop-down options but only thing is that I don't want that space to be get displayed when selection shown above

can anyone please tell me some solution to prevent the space to display when selection

My code is as given below

JSFiddle

<select>
    <option ng-repeat="(key, value) in headers">{{value | space}}
    </option>
</select>

Upvotes: 3

Views: 3024

Answers (5)

vtor
vtor

Reputation: 9319

Given your code, you can add one helper directive, to remove space in link function, once your option got selected.

As an example, add an id to your select, and directive

<select id="mySelect" option-without-space>
    <option ng-repeat="(key, value) in headers">{{value | space}}
    </option>
</select>

And directive might look like,

app.directive('optionWithoutSpace', () => {
        return {
            restrict: 'A',
            link: function(scope, elem, attributes) {

                var selectedOptionWithoutSpace = function () {
                    var selectedOption = $('#mySelect option:selected');

                    var optionText = selectedOption.text();

                    selectedOption.text(optionText.trim())

                    return false;
                };

                $(elem).on('change', selectedOptionWithoutSpace);

            }
        }
    })

This is with a little help of jQuery, but I assume it is not a big problem.

Here is a fiddle.

Upvotes: 3

G-Host
G-Host

Reputation: 376

<select ng-model="selectedValue" ng-change="selVal = selectedValue.trim(); selectedValue=selVal">
    <option ng-if="selVal">{{selVal}}</option>
    <option ng-repeat="(key, value) in headers" ng-if="selVal != value.value">
        {{value | space}}
    </option>
</select>

Upvotes: 3

Joe Enzminger
Joe Enzminger

Reputation: 11190

First off, this was a great question. I've unfortunately spent way too much time trying to come up with a solution to this. I've tried everything from CSS, to using ngModelController $formatters, to the solution (which isn't optimal as you'll see) I've posted below. Note, I do not think my solution deserves to be selected as the answer. It just "sorta" works, but like other solutions, it has a fatal flaw.

However, since your question was:

can anyone please tell me some solution to prevent the space to display when selection

My official answer is:

No

There is no cross-browser way to get this working. No amount of CSS, jQuery, or Angular magic will make this work. While it may be disappointing, I think that is going to be the only correct answer to your question.

No one is going to be able to give you a solution that prevents the space from being displayed in the select box while maintaining it in the options that works reliably across browsers. Chrome and Firefox allow some amount of styling of elements in the select, options, and optgroup family, but nothing is consistent and works everywhere.

My best run at it is in this Plunk

It uses the fact that optgroup will do indentations for you, but it comes with terrible differences in how different browsers handle it. With some you can style away the problem, but others do not work (and never will). I'm posting it so maybe someone will be inspired and figure out a way to prove me wrong.

<body ng-app="app">
  <div ng-app='myApp' ng-controller="ArrayController">
    <div>{{selectedValue}}</div>

    SELECT:
    <select ng-model="selectedValue" >
      <option indented="item.mainId" ng-repeat="item in headers">{{item.value}}</option>
    </select>
  </div>
</body>

(function() {

  var app = angular.module('app', []);
  app.controller('ArrayController', function($scope, $timeout) {
    $scope.headers = [{
      value: 'value 1'
    }, {
      value: 'value 2',
      mainId: 12
    }, {
      value: 'value 3'
    }, {
      value: 'value 4',
      mainId: 14
    }, {
      value: 'value 5'
    }, {
      value: 'value 6',
      mainId: 18
    }];
  });

  app.directive('indented', function($parse) {
    return {
      link:function(scope, element, attr){
        if($parse(attr.indented)(scope)) {
          var opt = angular.element('<optgroup></optgroup>');
          element.after(opt).detach();
          opt.append(element);
        }
      }
    };
  });
})();

If you opened the question up and allowed the implementation of a directive that mimicked the behavior of select but was instead built with li elements, then this would be trivial. But you simply can't do it with select.

Upvotes: 3

downhand
downhand

Reputation: 395

This is as close as it gets without jquery, temporarily changing the view state of the option when it's chosen. If that doesn't satisfy you and you still want it to be shown indented when the dropdown menu is open, check out this question on how to detect the state of the select component and update the display function accordingly. Alternatively, you can create your own select directive and manage the details within that, but I doubt that's worth the trouble if you're not using it in many places.

var app = angular.module('myApp', []);

app.controller('ArrayController', function ($scope) {
    $scope.headers = [{
        value: 'value 1'
    }, {
        value: 'value 2',
        mainId: 12
    }, {
        value: 'value 3'
    }, {
        value: 'value 4',
        mainId: 14
    }, {
        value: 'value 5'
    }, {
        value: 'value 6',
        mainId: 18
    }];

    $scope.chosen = $scope.headers[0].value;

    $scope.display = function(header) {
        var chosenObject = _.find($scope.headers, {value: $scope.chosen});
        if (!_.isUndefined(header.mainId) && header !== chosenObject) {
            return '\u00A0\u00A0' + header.value;
        } else {
            return header.value;
        }
    }
});

HTML here:

<div ng-app='myApp' ng-controller="ArrayController">
    <br></br>
    SELECT:
    <select ng-model="chosen" ng-options="header.value as display(header) for header in headers">
    </select>
</div>

There's yet another alternative with CSS and ng-class, fiddle here:

var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
    $scope.headers = [{
        value: 'value 1'
    }, {
        value: 'value 2',
        mainId: 12
    }, {
        value: 'value 3'
    }, {
        value: 'value 4',
        mainId: 14
    }, {
        value: 'value 5'
    }, {
        value: 'value 6',
        mainId: 18
    }];

    $scope.chosen = $scope.headers[0].value;

    $scope.isIndented = function(header) {
        var chosenObject = _.find($scope.headers, {value: header});
        return !_.isUndefined(chosenObject.mainId);
    };
});

app.filter('space', function() {
  return function(text) {
       if(_.isUndefined(text.mainId))
       {
           console.log('entered mainId');
           return text.value;
       }
       else
       {
           console.log('entered');
           return '\u00A0\u00A0' + text.value;
       }
  };
});

HTML:

<div ng-app='myApp' ng-controller="ArrayController">
    <br></br>
    SELECT:
    <select ng-model="chosen" ng-options="header.value as (header | space) for header in headers" ng-class="{'indented-value': isIndented(chosen)}">
    </select>
</div>

CSS:

.indented-value {
    text-indent: -9px;
}

Upvotes: 3

Deenadhayalan Manoharan
Deenadhayalan Manoharan

Reputation: 5444

Try this...

Change select box html following

<select ng-model="selectedOption" ng-options="item.value for item in headers"></select>


var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
    $scope.headers = [{
        value: 'value 1'
    }, {
        value:'value 2',
        mainId: 12
    }, {
        value: 'value 3'
    }, {
        value: 'value 4',
        mainId: 14
    }, {
        value: 'value 5'
    }, {
        value: 'value 6',
        mainId: 18
    }];
    $scope.selectedOption = $scope.headers[0]; //Add this line
});

app.filter('space', function() {
  return function(text) {
       if(_.isUndefined(text.mainId))
       {
           console.log('entered mainId');
           return text.value;
       }
       else
       {
           console.log('entered');
           return '\u00A0\u00A0' + text.value;
       }
  };
});

Upvotes: -1

Related Questions