3

I have an angular directive like so:

'use strict';

angular.module('countrySelect', [])
  .directive('countrySelect', ['$parse', function($parse) {
    var countries = [
      { code: "af", name: "Afghanistan" },
      { code: "ax", name: "Åland Islands" },
      { code: "al", name: "Albania" },
      { code: "dz", name: "Algeria" },
    ];

    return {
      template: '<select ng-options="c.code as c.name for c in countries">',
      replace: true,
      link: function(scope, elem, attrs) {
        scope.countries = countries;

        if (!!attrs.ngModel) {
          var assignCountry = $parse(attrs.ngModel);

          elem.bind('change', function(e) {
            assignCountry(elem.val());
          });

          scope.$watch(attrs.ngModel, function(country) {
            elem.val(country);
          });
        }
      }
    }
  }]);

And a select field in the template like so:

<div country-select ng-model="citizenship"></div>

I can select an option, and the model gets updated with the country code as intended, but the country name does not appear in the select field unless I choose it again.

In other words, the process goes

  1. click
  2. select country
  3. model gets updated with country code but name does not appear in select field
  4. click and select again
  5. name appears in the select field

How do I get the select field to display the country name upon select?

2 Answers 2

2

Since you are using replace: true original ng-model="citizenship" is going to end up on select element anyway, so you don't need to handle select change events in order to update ngModel, it's already bound to select box. So your directive should look just like this:

angular.module('countrySelect', [])
.directive('countrySelect', [function() {
    var countries = [
        { code: "af", name: "Afghanistan" },
        { code: "ax", name: "Åland Islands" },
        { code: "al", name: "Albania" },
        { code: "dz", name: "Algeria" },
    ];

    return {
        template: '<select ng-options="c.code as c.name for c in countries"></select>',
        replace: true,
        link: function(scope, elem, attrs) {
            scope.countries = countries;
        }
    }
}]);

Demo: http://plnkr.co/edit/9aBhrlIqPIGkGTNTwIb6?p=preview

Sign up to request clarification or add additional context in comments.

Comments

0

You might want to use $apply() to "force update" the view. http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

1 Comment

Thanks, but dfsq's solution just involves removing a bunch of code without adding complexity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.