0

I am unable to access the value of the selected option, I think I'm making a mistake in providing the ng-model to the select menu or kind of that.

(HTML) select option

<select id="countryListId"></select>

(AngularJS Controller)

        $scope.fetchCountries = function() {

        var $selectCountry = $('#countryListId'); 

        $.ajax( {
            url: 'http://.../someurl/dropdown?typ=Countries',
            dataType: 'JSON',
            success: function(data) {

                $selectCountry.html('<select ng-model="locationForm.country"></select>');
                $.each(data, function(key, val) {
                    $selectCountry.append('<option value="' + val.code + '">' + val.value + '</option>');
                })
            }, error: function() {
                $selectCountry.html('<option id="-1">none available</option>');
            }
        }); 

    }

The code works fine, and shows me the populated dropdown with the data fetched from the url, but:

when I select an option and try to access the selected value through ng-model: I get null

So, I would like you to please guide me through the proper way of providing the ng-model via Ajax or anything else through which I can get the selected option.

Sikandar Sahab
  • 638
  • 3
  • 10
  • 27

2 Answers2

1

This is happening because your angular is not aware about the change you made through jquery. Understand this https://stackoverflow.com/a/15012542/687280

Amit Naik
  • 43
  • 8
1

Use an array (in this case $scope.dataselect =[]) will keep the data that is being fetched from API. And bind it to your template option element as follows:

<select ng-model="locationForm.country">
   <option ng-repeat="data in dataselect" value="{{data.code}}">{{data.value}}</option>
</select>

At the controller, set or push data to the array( $scope.dataselect) on the current scope in the success callback. If the data changed then the view will automatically update. You don't need to update the view manually. You can also use $http service.

app.controller('myCtrl', function($scope, $http) {
  $scope.fetchCountries = function() {
    $scope.dataselect = []; // something [{code:"1",value:"data1"},{code:"2",value:"data2"}]
    $http.get("http://.../someurl/dropdown?typ=Countries")
    .then(function(data) {
       angular.forEach(data, function(val, key) {
        var elem = {key:val.code,value:val.value};  
        $scope.dataselect.push(elem);
       })
    }, function(response) {
        //handles error
        $scope.dataselect = [{code:"-1",value:"Not available"}]
    });
  });
});

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

app.controller('MainCtrl', function($scope,$http) {
 $scope.dataselect =[];
 $scope.update = function() {
  console.log("changed "+$scope.locationForm.country);
}
 $scope.fetchCountries = function() {

  $scope.dataselect =[];
  $scope.dataraw ={"code1":"value1","code2":"value2"}; //dummy from API
   angular.forEach($scope.dataraw, function(val, key) {
    
     var elem = {key:key,value:val};
          
     $scope.dataselect.push(elem);
   })
 }
 
 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainCtrl ">
    {{locationForm.country}}
  <select  ng-change="update()" id="countryListId" ng-model="locationForm.country">
    <option ng-repeat="data in dataselect" value="{{data.key}}">{{data.value}}</option>
  </select>
  <button ng-click="fetchCountries()">Fetch</button>
</div>

Solution 2: (for the sake of explanation)

But, if you want just to use jQuery#html function then you should create wrapper element as follows:

<div id="select-container-js">
    <select id="countryListId"></select>
</div>

And now you can use it. But in this case, you need also invoke $compile to compile the DOM with new element and link it to the current scope.

$('#select-container-js').html('<select  id="countryListId" ng-model="locationForm.country"></select>');
//you should set $selectCountry just before using it because of reference losing.
var $selectCountry = $('#countryListId');
$.each(data, function(key, val) {
  $selectCountry.append('<option value="' + val.code + '">' + val.value + '</option>');
})
$compile($selectCountry)($scope);   

Not: Don't forget to inject $compile service into your controller.

app.controller('MainCtrl', function($scope,$compile) {}
Gurkan Yesilyurt
  • 2,635
  • 2
  • 20
  • 21