Search code examples
angularjsangularjs-ng-repeatangular-directiveangularjs-moduleui.bootstrap

Angular JS: How to use ng-repeat with custom directive and dynamic model?


I've a template as follows:

<div class="row search-panel">
    <div ng-show="loadingAirports">
        <i class="glyphicon glyphicon-refresh"></i> Searching...
    </div>
    <div ng-show="noResults">
        <i class="glyphicon glyphicon-remove"></i> No Results Found
    </div>
    <div class="col-md-6">
        <pre>Source: {{srcAirport | json}}</pre>
        <p class="input-group">
            <input type="text" class="form-control" ng-model="srcAirport" uib-typeahead="airport as airport.name for airport in findAirports($viewValue)"
                   typeahead-min-length="3" typeahead-loading="loadingAirports" typeahead-no-results="noResults">
        </p>
    </div>
    <div class="col-md-6">
        <pre>Destination: {{destAirport | json}}</pre>
        <p class="input-group">
            <input type="text" class="form-control" ng-model="destAirport" uib-typeahead="airport as airport.name for airport in findAirports($viewValue)"
                   typeahead-min-length="3" typeahead-loading="loadingAirports" typeahead-no-results="noResults">
        </p>
    </div>
</div>

And a custom directive that uses the above template:

(function() {
  var app = angular.module('airport-search', ['ui.bootstrap']);

  app.directive('airportSearch', function() {
    var airportSearchCtrl = ['$scope',
      function($scope) {
        $scope.airports = {
          "data": [{
            "name": "Le Touquet Paris Plage",
            "city": "Le Tourquet",
            "country": "France",
            "faa_code": "LTQ",
            "icao": "LFAT",
            "time_zone_offset": "+01:00"
          }, {
            "name": "Sparrevohn Lrrs",
            "city": "Sparrevohn",
            "country": "United States",
            "faa_code": "SVW",
            "icao": "PASV",
            "time_zone_offset": "-09:00"
          }, {
            "name": "Palm Beach Co Park",
            "city": "West Palm Beach",
            "country": "United States",
            "faa_code": "LNA",
            "icao": "KLNA",
            "time_zone_offset": "-05:00"
          }, {
            "name": "Scappoose Industrial Airpark",
            "city": "San Luis",
            "country": "United States",
            "faa_code": "SPB",
            "icao": "KSPB",
            "time_zone_offset": "-08:00"
          }, {
            "name": "Sheppard Afb Wichita Falls Muni",
            "city": "Wichita Falls",
            "country": "United States",
            "faa_code": "SPS",
            "icao": "KSPS",
            "time_zone_offset": "-06:00"
          }]
        };

        $scope.findAirports = function(val) {
          return new Promise(function(resolve, reject) {
            resolve($scope.airports);
          }).then(function(searchResults) {
            return searchResults.data.map(function(airport) {
              return airport;
            });
          });
        };
      }
    ];

    return {
      restrict: 'E',
      templateUrl: 'airport-search.html',
      scope: {
        srcAirport: '=',
        destAirport: '='
      },
      controller: airportSearchCtrl
    };
  });
})();

This works but as you can see, the template repeats the attributes for the text fields except for the model. It'd be nice to be able to use ng-repeatand then vary the model. I tried with ng-repeat="model in [srcAirport, destAirport] track by $index" but that didn't compile. Can this be done?

Here a live Plunker example.


Solution

  • You can do it like this:

    <div class="col-md-6" ng-repeat="model in [srcAirport, destAirport] track by $index">
      <pre>Model: {{model | json}}</pre>
      <p class="input-group">
            <input type="text" 
                   class="form-control" 
                   ng-model="model" 
                   uib-typeahead="airport as airport.name for airport in findAirports($viewValue)"
                   typeahead-min-length="3" 
                   typeahead-loading="loadingAirports" 
                   typeahead-no-results="noResults">
        </p>
    </div>
    

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