I'm using angular-bootsrap typeahead to provide a search functionality. For some cases the search data is almost consisting of more than 200 items which is taking a lot of time to create the DOM. What should be the best way to handle this amount of data? I tried to create a custom typeahead template consisting of pagination, however I'm not able to see anything being created in the DOM. This is where I stand :
The HTML
<td id="scrollable-dropdown-menu">
<input type="text" ng-model="item.product"
placeholder="Search Product...."
uib-typeahead="product as product.name for product in searchProduct($viewValue)" typeahead-loading="loadingLocations"
typeahead-no-results="noResults"
typeahead-popup-template-url="customTypeaheadTemplate.html"
class="form-control">
<i ng-show="loadingLocations" class="fa fa-spinner" aria-hidden="true"></i>
<div ng-show="noResults">
<i class="fa fa-times" aria-hidden="true"></i> No Results Found
</div>
</td>
customTypeaheadTemplate.html
<script type="text/ng-template" id="customTypeaheadTemplate.html">
<div class="">
<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+'px', left: position().left+'px'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">
<li style="border-bottom: solid 1px lightgray" class="customFadeAnimate" ng-repeat="match in matches | startFrom:(currentPage*8)-8 | limitTo: 8 track by $index " ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">
<div typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>
</li>
<div ng-click="$event.stopPropagation()" ng-hide="matches.length - 8 < 1" style="text-align:center;margin: 5px;color: #808080;min-width:250px">
<span> {{((currentPage || 1)*8)-8+1}} to {{((currentPage || 1)*8 > matches.length) ? matches.length : (currentPage || 1)*8}} of {{matches.length}} </span>
<pager style="margin-top:-20px;margin-bottom:4px" total-items="matches.length" ng-model="currentPage" items-per-page="8" align="true" previous-text="Prev" next-text="Next"></pager>
</div>
</ul>
</div>
</script>
The JS
$scope.searchProduct = function(viewValue){
$scope.invalidProduct = false;
if(viewValue.length < 3){
return;
}
return $http.get('/api/v1/searchProducts', {
params: {
compId: user.companyId,
name: viewValue
}
}).then(function(response){
return response.data.map(function(item){
item.quantity = 1;
item.discount = 0;
item.tax = 0;
if(item.gst != null){
item.tax = item.gst.rate;
}
item.subtotal = item.quantity * item.mrp
item.subtotal = item.subtotal - (item.subtotal * item.discount/100);
item.subtotal = item.subtotal + (item.subtotal * item.tax/100);
return item;
});
});
}
Sample JSON (item)
{
"id": 858,
"name": "COVER OIL FILTER",
"mrp": 15,
"sp": 0,
"cp": 0,
"stocks": 0,
"isPublished": true,
"partNumber": "15441KWS900S",
"category": {
"id": 2,
"name": "oil",
"created_at": "2017-06-03T10:29:44.000Z",
"updated_at": "2017-06-03T10:29:44.000Z",
"company_id": 1,
"tax": 0
},
"gst": {
"id": 1,
"rate": 28,
"name": "87141090",
"remark": "NULL",
"created_at": "2017-07-22T14:28:38.000Z",
"updated_at": "2017-07-22T14:28:38.000Z",
"company_id": 1
},
"quantity": 1,
"discount": 0,
"tax": 28,
"subtotal": 19.2
}