0

I'm using Alpaca forms and pulling values for a form autocomplete field from a web service. I've worked through how to use this data as values for the autocomplete using jQuery and now need to use this data source within Alpaca forms, which uses typeahead.js and Bloodhound.js. I'm not quite sure how Alpaca interacts with these other JS libs. The code below returns an array of values in the autocomplete field, but of course only the matching value should be displayed and selectable. I'm not sure if I need to create a Bloodhound instance and parse the array matches there or handle this within the "suggestions" template. I've tried both so far without success.

<html>
    <head>
        <title>Alpaca-Autocomplete Form</title>
        <link type="text/css" rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />

        <!-- jQuery -->
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

        <!-- Bootstrap -->
        <script type="text/javascript" src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>

        <!-- Handlebars --> 
        <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.3/handlebars.js"></script>

        <!-- Alpaca -->
        <link type="text/css" href="http://code.cloudcms.com/alpaca/1.5.14/bootstrap/alpaca.min.css" rel="stylesheet" />
        <script type="text/javascript" src="http://code.cloudcms.com/alpaca/1.5.14/bootstrap/alpaca.min.js"></script>

        <!-- jQuery UI Support --> 
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
        <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css">

        <!-- typeahead.js https://github.com/twitter/typeahead.js -->
        <script src="bower_components/typeahead.js/dist/bloodhound.min.js" type="text/javascript"></script>
        <!-- <script src="bower_components/typeahead.js/dist/typeahead.bundle.min.js" type="text/javascript"></script> -->
        <script src="typeahead-0.10.5.bundle.min.js" type="text/javascript"></script>    
    </head>
    <body>
    <div id="field7"> </div>
    <script>
        $("#field7").alpaca({
            "schema": {
                "type": "string"
            },
            "options": {
                "type": "text",
                "label": "Input Parameter DataType",
                "helper": "Select the name of the input parameter data type",
                "typeahead": {
                    "config": {
                        "autoselect": true,
                        "highlight": true,
                        "hint": true,
                        "minLength": 1,
                        "data": {
                            "q": "request.term"
                        }
                    },
                    "datasets": {
                        "type": "remote",
                        "name": "data",
                        "displayKey": function(data) {
                            console.log("** displayKey function called **")
                            return data.field_values.buckets;
                        },
                        "source": "http://smart-api.info/api/suggestion/?field=services.inputParameter.parameterDataType",
                        "displayKey": function(source) {
                            var arr = source.buckets; 
                            var results = [];
                            var dataKeys = source.buckets.map(function (x) {
                                results.push({"value": x.key}); //expected data format for type: remote for Alpaca
                                return x.key // key is the name of the key to extract the value for display 
                            });
                            console.log(dataKeys);
                            return dataKeys;   
                        },
                        "templates": function(dataKeys){
                            var matcher = new RegExp( "\\b" + $.ui.autocomplete.escapeRegex( request.term ), "i" ); 
                            response( $.grep( dataKeys, function( item ){
                                return matcher.test( item );
                            }) );
                        }

                    }
                }
            }
        });
    </script>
    </body>
</html>
tw1742
  • 1,424
  • 4
  • 18
  • 37

1 Answers1

1

First to show key values correctly and not an array of keys you have to use Bloodhound, so before initializing alpaca use bloodhound to filter and process your data like this :

    var data = new Bloodhound({
       datumTokenizer: Bloodhound.tokenizers.whitespace,
       queryTokenizer: Bloodhound.tokenizers.whitespace,
       remote: {
         url: 'http://smart-api.info/api/suggestion/field=services.inputParameter.parameterDataType',
         filter: function(data) {
         // Map the remote source JSON array to a JavaScript object array
             return $.map(data.field_values.buckets, function(bucket) {
                return {
                  value: bucket.key
                };
             });
         }
       }
    });

    data.initialize();

Then in your alpaca config set displayKey to value and source to data.ttAdapter()

"datasets": {
    "name": "data",
    "displayKey": 'value',
    "source": data.ttAdapter()
}

With this I don't get the wanted value, because the problem here is with the datasource you're using, I tried to use another datasource that uses the %QUERY string and it worked perfectyl. For this kind of datasource I tried to use localinstead of remote and it worked. Try it yourself and tell me if it works.

Here's some mock datasource examples :

And here's a fiddle, I added another datasource that uses a %QUERY string, try to use local and remote in data (see the comments) and try next to use the other datasource movies in alpaca config.

Hope this helps.

Oussama BEN MAHMOUD
  • 1,442
  • 12
  • 19
  • Yeah, that helps! Is there a way to also limit the display to only matching terms? – tw1742 Dec 07 '15 at 18:00
  • I made some edits based on http://stackoverflow.com/questions/22059933/twitter-typeahead-js-how-to-return-all-matched-elements-within-a-string to change the datumTokenizer and remote to prefetch. My edits have to be peer reviewed so might not be visible yet. – tw1742 Dec 07 '15 at 19:12
  • I tried many solutions, I think there's a problem with your datasource response format or something, I don't know but its weird when I change the datasource it works like a charm! – Oussama BEN MAHMOUD Dec 07 '15 at 20:13
  • Your solution worked to return results as a list and got me much further than I was before to a solution, but the entire list was displayed vs. only the matching terms. With your code and the new update, only the matching term is displayed. The web service response is from ElasticSearch Terms Aggregation w/o changes to be friendly for autocomplete aka do more of the work on the server side. – tw1742 Dec 07 '15 at 20:33