4

AngularJS has ngAutoComplete that works with Google place perfectly.

How can I make it work with Google Suggest API (the suggested keywords when typing in Google Search input box)? Is there something out of the box?

If not, what is the best way to implement it? (if I need my own API interface - how should I make the connection)?

EDITED

Google Suggest API will return XML for the following call. If I want to return JSON it needs to be passed via my server side to translate it. It could also be an option if you suggest so

http://google.com/complete/search?output=toolbar&q=theory&gl=in

Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101
Dejell
  • 13,947
  • 40
  • 146
  • 229

2 Answers2

4

You can add this to the remote-url -

https://www.google.com/s?sclient=psy-ab&biw=1242&bih=395&q=ThisIsTheSearchString&oq=&gs_l=&pbx=1&bav=on.2,or.r_cp.&bvm=bv.93112503,d.cWc&fp=160df26a97fa030e&pf=p&sugexp=msedr&gs_rn=64&gs_ri=psy-ab&tok=_1hxlqgFnvRgVdHXR4t-nQ&cp=10&gs_id=51&xhr=t&es_nrs=true&tch=1&ech=37&psi=O5FTVZiMAfPisASwnYH4Cg.1431540027601.1

Make ThisIsTheSearchString a var that changes on key stroke. Before you put the url into the ngAutoComplete make sure to encode the string - escape(ThisIsTheSearchString); This will help if there are any white spaces in the search.

I got the URL by going to google and watching the network tab. It will return a .txt file that you will have to read. Also you will need a regex to compile the file.

Jacob Finamore
  • 797
  • 5
  • 19
3

Updated Version (Custom Directive ngGoogleSuggest)

click Plunker

Directive performs much better because on keyup performs a http call to GoogleSuggest API

    elem.bind('keyup', scope.search);

Markup:

  <div data-ng-google-suggest ng-model="Search"></div>

Note: I plan to make a GitHub repo for ngGoogleSuggest after it has been tested a bit more


Screen Shots

enter image description here

Calling Google Search API

  • End Point: 'http://suggestqueries.google.com/complete/search
  • for JSON response (not XML), add param &client=firefox
  • Uri Encoded search Parameter
  • use JSONP protocol by adding ?callback=JSON_CALLBACK to avoid Access-Control-Allow-Origin Error

example $http call

    scope.search = function() {
      // If searchText empty, don't search
      if (scope.searchText == null || scope.searchText.length < 1)
        return;

      var url = 'http://suggestqueries.google.com/complete/search?';
      url += 'callback=JSON_CALLBACK&client=firefox&hl=en&q=' 
      url += encodeURIComponent(scope.searchText);
      $http.defaults.useXDomain = true;

      $http({
        url: url,
        method: 'JSONP',
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
          'Content-Type': 'application/json',
          'Accept': 'application/json'

        }
      }).
      success(function(data, status, headers, config) {

        // Api returns [ Original Keyword, Searches[] ]
        var results = data[1];
        if (results.indexOf(scope.searchText) === -1) {
          data.unshift(scope.searchText);
        }
        scope.suggestions = results;
        scope.selectedIndex = -1;
      }).
      error(function(data, status, headers, config) {
        console.log('fail');
        // called asynchronously if an error occurs
        // or server returns response with an error status.
      });
Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101
  • 1
    now plunker works fine! I am not sure about the directive - as I am not so fluent with Angular.js - I am curious as you wrote: I suspect a directive needs to wrap this for optimal performace – Dejell May 14 '15 at 15:35
  • @Dejel, made a new directive. Tell me what you think of this Plunker. It's not quite done, but is it close? http://plnkr.co/edit/znqKCyseooyUxC7lxmst?p=preview – Dave Alperovich May 14 '15 at 15:56
  • 1
    wow! looks fantastic. it's 0:03 AM by me - so tomorrow morning I will verify more and accept the answer. Wow amazing! – Dejell May 14 '15 at 21:03
  • I was just trying to print the selected value like this {{searchText}} in index.html and the value is empty. any reason? – Dejell May 15 '15 at 07:25
  • @Dejel, try `{{ Search }}` -- ignore what the value is inside the Directive. `ng-model` is bound to Search. Refresh the Plunker, I saved it inside index.html – Dave Alperovich May 15 '15 at 07:31
  • @Dejel was a fun project. I think you had a great idea. I'll still be adding features to it and will publish it to GitHub Repo. So let me know if anything more needs tweaking. – Dave Alperovich May 15 '15 at 08:01
  • thank you!! - please add a comment when you add to a github project so I will get a notification :) – Dejell May 15 '15 at 08:03
  • something else that I was thinking about - shouldn't the css be refered from the directive like the template? – Dejell May 15 '15 at 08:38
  • @Dejel, usually unique classes are chosen for each component you might want to customize within the Directive. This way you can customize the feel without altering the template. I added a class in template for highlighting choices. But no others so far. If you see areas where custom classes should be, email me. You can find the email on my profile. I'll add classes to template and to the Gist later. – Dave Alperovich May 15 '15 at 08:43
  • thanks! I tried to add it to my code (in an existing app) but it wouldn't show the directive, although I see in grunt serve console that the autocomplete.html page was loaded fine via GET command. any reason for it? – Dejell May 15 '15 at 10:42
  • @Dejel, I would guess that you that you did not add the new app as a dependancy of your current app. In the Plunker I have an attribute in the body `ng-app="GoogleSuggest"`. You have a similar `ng-app="MyApp"`. When declaring MyApp, you would add all dependant apps: `angular.module('MyApp', ['ngRoute', 'GoogleSuggest', ...]);` But this is the most likely guess. If you showed me the url, I could take a closer look. – Dave Alperovich May 15 '15 at 15:10
  • nope it didn't help. I see that instead of embedding the directive, it adds my index.html file. I will upload a new version with it later – Dejell May 17 '15 at 07:11
  • @Dejel, show me a link and I can take a better look. Another approach is to make the directive a member of your current app. As I defined it as a child of the `GoogleSuggest` module, you can make the directive a child of your Angular App module. – Dave Alperovich May 17 '15 at 07:35