简体   繁体   中英

Why does angularjs include an empty option in select using directive with transclude and replace

I am creating a new directive for the select element. As a best practice, I would like to receive some of the options from the server and one option I want to create in the client code eg "Search all cars".

This is an example of how I want it to look:

<select>
  <option value="">Search all cars</option>
  <option value="aud">Audi</option>
  <option value="bmw">BMW</option>
  <option value="maz">Mazda</option>
</select>

It is important that the value of "Search all cars" is empty.

But even though I have added an empty element in the select (ref other SO posts ) it still gives me an unwanted option:

<option value="?" selected="selected"></option>

Here is an plunker example of the issue/bug using an Angular directive with transclude and replace.

Anyone got a suggestion of how to solve this?

I have also added an issue to the angular team here .

EDIT:

The reason why I would like to have this as an directive is that I want to decide if I should have the "Search all cars" option or not depending on where it is implemented in my application.

EDIT2: Angular team confirms that this is a bug. "It looks like the root reason is that if an unknown option is added after the initial setup, then it will not replace the generated unknown option" - lgalfaso .

@Yoshi is right, it's to do with ngTransclude . As soon as you move the default option into the directive itself, the problem goes away. To work around this issue, since you don't care about the default value so much, you can modify the directive slightly and just import the text for the default option:

app.directive('mySelect', [function () {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      default: '@'
    },
    template: '<select ng-options="key as value for (key, value) in myMap"><option value="">{{ default }}</option></select>',
    link: function postLink(scope, element) {
      scope.myMap = {"bmw":"BMW","maz":"Mazda","aud":"Audi"}; // e.g. hashmap from server
    }
};

And then your HTML becomes:

<my-select ng-model="myModel" ng-change="doSomething(myModel)" default="Search all cars">
</my-select>

I just had the same issue as you and unfortunately @morloch's answer did not help me. In my case, the transclusion is dynamic.

I started with your plunker and figured out that, if we use the transclusion during the prelink, it solves the issue.

   link: {
      pre:function preLink(scope, element, attrs, controllers, transcludeFn) {
        scope.myMap = {"bmw":"BMW","maz":"Mazda","aud":"Audi"}; // e.g. hashmap from server
        transcludeFn(scope, function(clone) {
          element.append(clone);
        });
      }
    } 

Here is my plunker : http://plnkr.co/edit/4V8r6iW2aKCLLbpIZc5e?p=preview

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM