Search code examples
javascriptflasktypeahead.jsbootstrap-tags-input

bootstrap tags input with typeahead throws (str || "").replace is not a function


in my last question it turned out that typeahead.js was probably updated typeahead autocomplete suggestion with ajax doesn't work. on bootstrap tags input there are some examples, so based on some code from my first question and examples I came out with code below. When I type for example s I get autosuggestion with dropdown Sandra but when I click on it I get this error every time: Uncaught TypeError: (str || "").replace is not a function

test.html

<html lang="en">
<head>
    <meta charset="utf-8"/>
  <link rel="stylesheet" href="/static/bootstrap.min.css">
  <link rel="stylesheet" href="/static/bootstrap-theme.min.css">
  <link rel="stylesheet" href="/static/bootstrap-tagsinput.css">

</head>
<body>
    <input type="text" data-role="tagsinput" >

<script src="../static/jquery.min.js"></script>
<script src="../static/bootstrap.min.js"></script>
<script src="../static/typeahead.bundle.js"></script>
<script src="../static/bootstrap-tagsinput.js"></script>


<script>
var citynames = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
      url: '/test/?query=*',
      wildcard: '*',
      filter: function(x) {
            return $.map(x, function(item) {
                console.log(item) //["Sandra"]
                return {name: item};
            });
        },
    },
});
citynames.initialize();

$('input').tagsinput({
  itemValue: 'name',
  typeaheadjs: {
    name: 'citynames',
    displayKey: 'name',
    source: citynames.ttAdapter()
  }
});
</script>

</body>
</html>

app.py

from flask import Flask, render_template, url_for, jsonify, request

app = Flask(__name__)

@app.route('/', methods=['GET','POST'])
def index():
    return render_template('test.html')

@app.route('/test/', methods=['GET', 'POST'])
def test():
    names = ["John","Jane", "Sandra", "Xerox"]
    query = request.args.get('query')
    return jsonify(options=[name for name in names if query.lower() in name.lower()])

if __name__ == '__main__':
    app.run(debug = True)

Solution

  • I solved my problem by doing this:

    var citynames = new Bloodhound({
      datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      remote: {
          url: '/test/?query=*',
          wildcard: '*',
          filter: function(list) {
              var arr = list.options
              var test = []
              for (var i =0; i<arr.length; i++) {
                test.push(arr[i])
              }
              list = test
              return $.map(list, function(item) {
                    console.log(item)
                    return {name: item};
                });
            },
        },
    });
    citynames.initialize();
    

    it's probably not the best way :D but it worked