Search code examples
jqueryjquery-select2

Select2- How to access property value of remote data - Cannot read properties of undefined


I am using select2 to fetch data via ajax from the url https://api.teleport.org/api/cities/. The request is able to return some json data, however, mapping the indexes to the select options returns a console warning message " Cannot read properties of undefined".

My intention is to get the value of the matching_full_name index from the json object.

$('.select2-cities').select2({
  ajax: {
    url: 'https://api.teleport.org/api/cities/',
    dataType: 'json',
    delay: 250,
    data: function(params) {
      return {
        search: params.term, // search term
        page: params.page
      };
    },

    processResults: function(data) {
      return {
        results: $.map(data, function(item) {
          return {
            text: item._embedded['city:search-results'].matching_full_name,
            id: item._embedded['city:search-results'].matching_full_name,
          }
        })
      };
    },

    cache: true
  },
  placeholder: 'Search for a city',
  minimumInputLength: 1,
});
<html>

<head>
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />

</head>

<body>
  <div class="row">
    <div class="col-md-12">
      <div class="form-group">
        <label class="w-100"> City</label>
        <select class="select2-cities form-control">

        </select>
      </div>

    </div>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>

</html>


Solution

  • Your code assumes the data returned is:

    data [array]
           _embedded
               city:search_results
    

    when it's actually

    data
        _embedded
               city:search_results [array]
    

    so looping $.map(data, (item) => gives item as the _embedded property as that's the first property of data. As such, there's no _embedded property of _embedded and you get your error.

    Instead, you need to loop the results array:

    results: $.map(data._embedded['city:search-results'], function(item) {
    

    Updated snippet

    $('.select2-cities').select2({
      ajax: {
        url: 'https://api.teleport.org/api/cities/',
        dataType: 'json',
        delay: 250,
        data: function(params) {
          return {
            search: params.term, // search term
            page: params.page
          };
        },
    
        processResults: function(data) {
          //console.log(data)
          return {
            results: $.map(data._embedded['city:search-results'], function(item) {
              //console.log(item)
              return {
                text: item.matching_full_name,
                id: item.matching_full_name,
              }
            })
          };
        },
    
        cache: true
      },
      placeholder: 'Search for a city',
      minimumInputLength: 1,
    });
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    
    
    <div class="row">
      <div class="col-md-12">
        <div class="form-group">
          <label class="w-100"> City</label>
          <select class="select2-cities form-control">
          </select>
        </div>
      </div>
    </div>