0

I have an Angular Project and am using UI-Bootstrap's Typeahead Directive.

The problem is that when using the typeahead directive to handle large amounts of similar data, I find that showing the top x number of results may not be sufficient for all users and conversely, it is too slow & impractical to show all of the results.

The idea is to provide a paging mechanism inside the pop-up of the typeahead control while still maintaining all existing functionality.

How can I solve this while still using the typeahead directive?

Gareth
  • 243
  • 1
  • 5
  • 12

1 Answers1

1

By using the $provide.decorator you can alter the HTML that is used by a directive to meet your own needs without changing how the directive works.

Do the following:

  1. Download the latest version of UI-Bootstrap here and find the directive you want to override as well as the html it uses. (In this instance, it's typeaheadPopup - or uibTypeaheadPopup if you're using the latest version)
  2. Copy the html string used by the directive and alter it to suit your needs. In this instance, make it use the following html: (I have limited my typeahead to 8 results but you can change that)

    <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>
    
  3. Create a Decorator Module to override the existing directive's html template with your own:

    (function () {
        'use strict';
    
        angular.module('app.decorators', ['ui.bootstrap'])
      .config(['$provide', Decorate]);
    
        function Decorate($provide) {
            $provide.decorator('typeaheadPopupDirective', function ($delegate) {
                var directive = $delegate[0];
    
                directive.templateUrl = "app/customTemplates/typeAheadPopup.html";
    
                return $delegate;
            });
        }
    })();
    

I have made use of the template functionality for this image - but you should achieve a similar result:

Typeahead Customisation Result

Note: You will need to append the name of the directive you wish to change with the word 'Directive'. You will also need to make sure that the decorator module you have created is referenced after the ui-bootstrap module in order for your template to take effect.

I have used the following stackoverflow answer as reference: SO Reference

Community
  • 1
  • 1
Gareth
  • 243
  • 1
  • 5
  • 12