Skip to content
Dane Rossenrode edited this page Apr 9, 2016 · 1 revision

This is a sample implementation of auto-complete, using RESTful on the back end, and Angular on the client side, shared by @adam-s.

The complete server code is at https://github.com/adam-s/954live/tree/master/livesource/src/Plugin/resource/livesearch and the complete client side code is at https://github.com/adam-s/954live/tree/master/livesearch.


My solution was to use a filter on the 'name' public field with an operator 'CONTAINS' and to make sure things didn't get crazy, added a 'range' of 10.

var url = '/api/v1.6/artists?filter[name][value]='
  + encodeURIComponent(queryString)
  + '&filter[name][operator]=CONTAINS&range=10'
  + '&filter[bundle]='
  + encodeURIComponent(bundle);

Where things get fun is there are two different bundles that a user can search for, in this case, artists or venues. So a bundle property is defined on public fields. Using the ability to define a wrapper_method, getBundle is used to return a bundle name to filter on.

<?php
/**
 * Maps to ArtistStyle
 */

namespace Drupal\livesource\Plugin\resource\entity\node\artists;

use Drupal\restful\Plugin\resource\ResourceNode;

/**
 * Class Artist__1_6
 * @package Drupal\livesource\Plugin\resource\entity\node\artists
 *
 * @Resource(
 *   name = "artists:1.6",
 *   resource = "artists",
 *   label = "Artists",
 *   description = "Export the artists with all authentication providers.",
 *   authenticationTypes = TRUE,
 *   authenticationOptional = TRUE,
 *   dataProvider = {
 *     "entityType": "node",
 *     "bundles": {
 *       "artists",
 *       "venues"
 *     },
 *   },
 *   majorVersion = 1,
 *   minorVersion = 6
 * )
 */

class Artists__1_6 extends ResourceNode {

    /**
     * {@inheritdoc
     */
    protected function publicFields() {

        $public_fields = parent::publicFields();
        $public_fields['name'] = $public_fields['label'];
        unset($public_fields['label']);

        $public_fields['bundle'] = array(
            'wrapper_method' => 'getBundle',
            'wrapper_method_on_entity' => TRUE,
        );

        return $public_fields;
    }
}

Here is what it looks like on the client side. I'm surprised how easy this is.

(function() {
    angular.module('livesearch')
        .factory('LivesearchApi', LivesearchApi);

    LivesearchApi.$inject = ['$http', '$q'];

    function LivesearchApi($http, $q) {
        var service = {
            list: list,
            getItem: getItem
        };

        return service;

        function list(queryString, timeoutPromise, bundle) {
            var deferred = $q.defer();

            var url = '/api/v1.6/artists?filter[name][value]='
                + encodeURIComponent(queryString)
                + '&filter[name][operator]=CONTAINS&range=10'
                + '&filter[bundle]='
                + encodeURIComponent(bundle);

           $http({
                'method': 'GET',
                'url': url,
                'timeout': timeoutPromise
            }).then(function(results) {
                console.log(results);
                deferred.resolve(results.data);
            });

            return deferred.promise;
        }
    }
})();
Clone this wiki locally