javascriptjquerytypeaheadbootstrap-typeaheadtwitter-typeahead

Bootstrap Typeahead not showing suggestion which have the valueKey starting with same value


I'm using typeahead v0.11.1 to show the result but it is not showing the result which have result starting with the same result.

The result I am getting from database is this :

Object {
  Id: 4,
  Title: "project manager",
  Description: "project manager",
  CompanyId: 1
}
Object {
  Id: 6,
  Title: "Software Developer",
  Description: "Software Developer",
  CompanyId: 1
}
Object {
  Id: 7,
  Title: ".NET Developer",
  Description: ".NET Developer",
  CompanyId: 1
}
Object {
  Id: 10,
  Title: "Android Developer",
  Description: "Android Developer",
  CompanyId: 1
}
Object {
  Id: 11,
  Title: "iOS Developer",
  Description: "iOS Developer",
  CompanyId: 1
}
Object {
  Id: 13,
  Title: "Sr. Android Developer",
  Description: "Sr. Android Developer",
  CompanyId: 1
}
Object {
  Id: 14,
  Title: "Sr. iOS Developer",
  Description: "Sr. iOS Developer",
  CompanyId: 1
}


The problem is typeahead is displaying all the result except
Sr. Android Developer and Sr. iOS Developer

var position = new Bloodhound({
    datumTokenizer: function (datum) {
        return Bloodhound.tokenizers.whitespace(datum.Title);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    //prefetch: '../data/films/post_1960.json',
    remote: {
        url: '/Search/Positions?query=%QUERY',
        wildcard: '%QUERY',
        filter:function (positionList) {
            // Map the remote source JSON array to a JavaScript object array
            return $.map(positionList, function (position) {
                console.log("position is:", position);
                return {
                    Title: position.Title
                };
            });
        }
    }
});
var promisepos=position.initialize();
promisepos.done(function(){});
$('#Position').typeahead({
    minLength:1,
    highlight:true,
    hint:false
},{
    name: 'positionList',
    displayKey:'Title',
    source:position.ttAdapter(),
    templates:{
        footer: "<div class='position-wrapper'><a class='ad-ps'><i class='fa fa-user-secret'></i> Add New Position</a></div>",
        notFound: function(){
            var ps=$('#Position').val();
            $('#PositionId').val("");
            return "<div class='position-wrapper'><p>No Position found.</p><a class='ad-ps'><i class='fa fa-user-secret'></i> Add New Position</a></div>";
        },
        suggestion: Handlebars.compile('<div class="position-wrapper">'+
                                        '<div class="poosition-info-wrapper">'+
                                            '<span>{{Title}}</span>'+
                                        '</div>'+
                                       '</div>')
    }
});

Solution

  • Note, Not certain about expected result of

    $("#PositionId").val("");
    

    ? ; html not appear at Question ; .typeahead() appear to be initialized at

    $("#Position")
    

    element , without "Id" within selector string ?


    The problem is typeahead is displaying all the result except Sr. Android Developer and Sr. iOS Developer

    Appear due to period character . within string value of Title property of returned obeject . .typeahead appear to match exact input value of query . e.g.,; if query was "sr" .typeahead would not match "Sr." ; if query was "sr." .typeahead would match "Sr. Android Developer" , "Sr. iOS Developer" . Adjusted test for returned matches that would be displayed within templates , within filter function at Bloodhound initialization ; removed period character "." from match test before results returned to templates. If query is "sr" , should return both "Sr. Android Developer" , "Sr. iOS Developer" . If query is "sr ios" , should return "Sr. iOS Developer" to templates for display as suggestion .

    Try creating setting Bloodhound.tokenizers.obj.whitespace to "value" ; returning object to templates suggestion callback function within filter at Bloodhound inititalization ; returning "suggestion" html at templates suggestion callback function , utilizing object passed at filter within Bloodhound initialization

    $(function() {
        var search = $(".typeahead-container #Position.typeahead");
        // `positions` settings
        var positions = new Bloodhound({
          // set `Bloodhound.tokenizers.obj.whitespace` to `"value"`
          datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value"),
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          remote: {
            url: "https://gist.githubusercontent.com/anonymous/"
                 + "cd07af7c8e3dbbeb601f/raw/"
                 + "936a69aa84e48c2cf96682ff044d3ace87750457/data.json"
                 + "?query=%QUERY",
            wildcard: "%QUERY",
            filter: function (pos) {
              return $.map(pos, function(positions) {
                // return `value` set to `positions`:`data` `Title`,
                // return `suggest` property having value set to `positions` object,
                // utilized at `suggestion` callback
                // remove periof character "." from match test
                return new RegExp(
                         search.val() 
                         + "|" 
                         + search.val().replace(".", "")
                       , "i")
                       .test(positions.Title.replace(".", ""))                
                       ? {
                         value: positions.Title,
                         suggest: positions
                       } 
                       : null
              })
            }
          }
          /*  
          // run with "local" data source ; e.g., `data`
          local: $.map(data, function(positions) {
            return {
              value: positions.Tile,
              suggest: positions
            }
          })          
          */
        });
        
        var promisepos = positions.initialize();
    
        promisepos
        .done(function() {
          console.log("positions initialized");
        })
        .fail(function() {
          console.log("positions initialization error");
        });
        
        search.typeahead({
          minLength: 1,
          highlight: true,
          hint: false
        }, {
          name: "positionList",
          displayKey: "Title",
          templates: {
            // set `templates` `footer` `html`
            footer: "<div class=position-wrapper>"
                    + "<a class=ad-ps><i class=fa fa-user-secret></i>"
                    + " Add New Position</a></div>",
            // set `templates` `notFound` `html`
            notFound: function() {
                        // not certain expected result of calling `.val()`
                        // on `#Position` ?, without argument passed to `.val()` ?
                        var ps = $('#Position').val();
                        // not certain expected result of setting 
                        // `#PositionId` `.val()` to empty string ?
                        $("#PositionId").val("");
                        return "<div class=position-wrapper>"
                               + "<p>No Position found.</p>"
                               + "<a class=ad-ps>"
                               + "<i class=fa fa-user-secret></i>"
                               + " Add New Position"
                               + "</a></div>";
            },
            // set `templates` `suggestion` `html`
            suggestion: function(data) {
                          // `data`: `positions` object passed at
                          // `Bloodhound` `remote` `local`
                          var details = "<div class=resultContainer>" 
                                        + "Title: "
                                        + "<b style=color:blue>" 
                                        + data.suggest.Title 
                                        + "</b>" 
                                        + "<div class=resultDesc>" 
                                        + "Description: <b>" 
                                        + data.suggest.Description 
                                        + "</b>" 
                                        + "</div>"
                                        + "<div class=resultLabel>Id: "
                                        + "<b>" 
                                        + data.suggest.Id 
                                        + "</b><br />" 
                                        + "Company Id: " 
                                        + "<b>"
                                        + data.suggest.CompanyId 
                                        + "</b>"
                                        + "</div></div>";
                          return details
    
            }
          },
          source: positions.ttAdapter()
        });
    });
    /* 
    // run with `local` data source
    // `data`: `"data.json"` ; e.g., `data` at `local`
    var data = [
      {
        "Id": 4,
        "Title": "project manager",
        "Description": "project manager",
        "CompanyId": 1
      },
      {
        "Id": 6,
        "Title": "Software Developer",
        "Description": "Software Developer",
        "CompanyId": 1
      },
      {
        "Id": 7,
        "Title": ".NET Developer",
        "Description": ".NET Developer",
        "CompanyId": 1
      },
      {
        "Id": 10,
        "Title": "Android Developer",
        "Description": "Android Developer",
        "CompanyId": 1
      },
      {
        "Id": 11,
        "Title": "iOS Developer",
        "Description": "iOS Developer",
        "CompanyId": 1
      },
      {
        "Id": 13,
        "Title": "Sr. Android Developer",
        "Description": "Sr. Android Developer",
        "CompanyId": 1
      },
      {
        "Id": 14,
        "Title": "Sr. iOS Developer",
        "Description": "Sr. iOS Developer",
        "CompanyId": 1
      }
    ];
    */
    .typeahead-container {
      font-family: sans-serif;
      position: relative;
      margin: 100px;
    }
    .typeahead,
    .tt-query,
    .tt-hint {
      border: 2px solid #CCCCCC;
      border-radius: 8px;
      font-size: 24px;
      height: 30px;
      line-height: 30px;
      outline: medium none;
      padding: 8px 12px;
      width: 396px;
    }
    .typeahead {
      background-color: #FFFFFF;
    }
    .typeahead:focus {
      border: 2px solid #0097CF;
    }
    .tt-query {
      box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
    }
    .tt-hint {
      color: #999999;
    }
    .tt-dropdown-menu {
      background-color: #FFFFFF;
      border: 1px solid rgba(0, 0, 0, 0.2);
      border-radius: 8px;
      box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
      margin-top: 12px;
      padding: 8px 0;
      width: 422px;
    }
    .tt-suggestion {
      font-size: 24px;
      line-height: 24px;
      padding: 3px 20px;
    }
    .tt-suggestion.tt-is-under-cursor {
      background-color: #0097CF;
      color: #FFFFFF;
    }
    .tt-suggestion p {
      margin: 0;
    }
    .resultContainer {
      width: 410px;
      border: 1px dotted grey;
      border-radius: 10px;
      padding: 4px;
      margin: 4px;
    }
    .resultDesc,
    .resultLabel {
      font-size: 14px;
      font-style: italic;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js">
    </script>
    <input type="text" id="PositionId" />
    <div class="typeahead-container">
      <input type="text" id="Position" class="typeahead tt-query" placeholder="positions" />
    </div>