Steve
Steve

Reputation: 1467

AngularJS UI Bootstrap typeahead with ajax using Coffeescript

My question is very similar to this post 'Using typeahead and ajax in a AngularJS app'

Coffeescript:

  $scope.tradingPartners = (searchOn) ->
    console.log("Searching on #{searchOn}")
    $.getJSON("../tp/tpLookupAdmin", {term: searchOn, max: 20}, (response)->
        response)

Generates Javascript:

$scope.tradingPartners = function(searchOn) {
      console.log("Searching on " + searchOn);
      return $.getJSON("../tp/tpLookupAdmin", {
        term: searchOn,
        max: 20
      }, function(response) {
        return response;
      });
    };

Using it:

<input type="text" ng-model="testScript.sender" typeahead="sender as sender.label for sender in tradingPartners($viewValue)" 

So whats wrong? ...

The getJSON call is made just fine, the results look good but the typeahead does not do anything. If I put hardcoded values in as the return from the function it works just fine.

Now I know the getJSON is not just returning an object array, and doing

$.getJSON("../tp/tpLookupAdmin", {term: searchOn, max: 20}, (response)->
        response).responseJSON

gives undefined.

Example hardcoded json that works:

[{"id":"1","label":"test1"},{"id":"2","label":"test2"}]

I'm missing something simple here...

Edit (from kju answer):

Now gen'd JS is

$scope.tradingPartners = function(searchOn) {
  return $http.post("../tp/tpLookupAdmin?term=" + searchOn).then(function(response) {
    return limitToFilter(response, 15);
  });
};

But its still not working...

Upvotes: 1

Views: 1626

Answers (2)

Steve
Steve

Reputation: 1467

In the end I went with using select2. I think its a cleaner more consistent approach in my case anyway.

<input ui-select2="tpSearch" ng-model="testScript.sender" class="input-xlarge"/>

CoffeeScript:

$scope.tpSearch =
    placeholder: "Type to search..."
    minimumInputLength: 2
    ajax:
      url: "../tp/tpLookupPaged"
      quietMillis: 100
      data: (term, page) ->
        term: term # query params 
        page: page
        max: 10
      results: (data, page) ->  
         more = (page * 10) < data.total
         results: data.results, more: more

Implementing infinite scroll was a breeze.

Make sure your JSON returns an array containing id and text or you'll have to write a custom formatter function for select2 (easy enough anyway)

Upvotes: 0

Juliane Holzt
Juliane Holzt

Reputation: 2145

The question you are referencing had already all the answers you need, so yours is really not a good question.

The lookup function must return either an array or a (AngularJS-style) promise. What you return is the return value of $.getJSON which is neither. The callback function in your code will return a array but to nowhere. It will not end up in Angular. This can't be helped because you are making an asynchronous HTTP request here. When the request returns, your lookup function has long returned before. Therefore you need to return a promise. AngularJS knows how to handle this promise and process the deferred data.

As I said, the other question and its accepted answer already has everything in it. Get rid of $.getJSOn and use the $http service from Angular as it is shown there.

Upvotes: 4

Related Questions