Reputation: 13
I'd like to add a custom footer to the results where I can wire up some paging. I see that I can specify a footer template in the options, but can't find any examples of how to set those options from a controller.
The footer template would display "Now showing 1-{{offsetEnd}} of {{result.count}} Load More
Thank you everyone!
This is the tag I'm using:
< input type = "text"
id = "search"
name = "search"
ng - model = "profile.selectedProfile"
typeahead = "o.itemvalue as o.itemtext for o in getProfiles($viewValue) | filter: $viewValue"
typeahead - input - formatter = "formatLabel($model)"
class = "form-control"
autocomplete = "off" / >
UPDATE I converted this to a directive, and incorporated a footer that displays the total record count.
function findProfile() {
return {
restrict: 'E',
template: '<input type="text" id="search" name="search" ng-model="selectedProfile" typeahead="o as o.itemtext for o in getProfiles($viewValue) | filter: $viewValue" typeahead-input-formatter="formatLabel($model)" class="form-control" autocomplete="off" />',
controller: function($scope, $http) {
$scope.itemCount = 0;
$scope.getProfiles = function(searchtext) {
return $http.get('http://localhost:61402/api/Profile/FindProfile?searchText=' + searchtext)
.then(function(response) {
$scope.itemCount = response.data.itemcount;
return response.data.items;
});
}
$scope.formatLabel = function(model) {
return model == undefined ? '' : model.itemtext;
}
}
};
}
And the template:
angular.run(['$templateCache',
function($templateCache) {
var template = '' +
'<ul class="dropdown-menu" ng-show="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">' +
'<li ng-repeat="match in matches 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>' +
'<li>Records Returned: {{$parent.itemCount}}</li>' +
'</ul>';
$templateCache.put('template/typeahead/typeahead-popup.html', template);
}
])
Upvotes: 1
Views: 1675
Reputation: 455
You have to override the typeahead template.
angular.module('app', ['ui.bootstrap'])
.run(['$templateCache', function ($templateCache) {
var template = '' +
'<ul class="dropdown-menu" ng-show="isOpen()" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">' +
'<li ng-repeat="match in matches 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>' +
'<li>The footer</li>' +
'</ul>';
$templateCache.put('template/typeahead/typeahead-popup.html', template);
}])
.controller('mainController', function($scope) {
$scope.selected = undefined;
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas'];
});
In this example, I copied the template of github-typeahead-template, the added a extra li
(the footer) element inside of the ul
element and, finally, I put the template in the angular's cache.
You can get a full example in custom angular-ui bootstrap and the template name https://github.com/angular-ui/bootstrap/blob/0.12.1/src/typeahead/typeahead.js#L452
This technique works with ui-bootstrap-tpls.js (include the templates) and the ui-bootstrap.js (without templates) but it is better to have the template in a file (typeahead-with-footer.html) than in a string. You have several options: use grunt, a script tag or create the static file (typeahead-with-footer.html) in you server (only works in with ui-bootstrap.js).
Upvotes: 0
Reputation: 10887
Ok, so I had to perform a bit of a hack here, but I liked your question.
What I ended up working with was the typeahead-template-url
. Unfortunately, the documentation for it is very hard to find, yet I had done a lot of work with this in the past. For some of the documentation, try here. Even more unfortunate, I never documented where I found the default typeahead-template-url
either, and I couldn't find it online today. Luckily, I did have my version of it on file.
Here is what I had before hacking at it:
<a>
<span bind-html-unsafe="match.model.label | myModelLabelFilter"></span>
</a>
As you can guess, this is the template
for each match shown in the Angular Typeahead
, and placing a filter
here (myModelLabelFilter
in our example) is a great way to modify and inject mostly whatever you want into each shown match.
Now, this may not have been the best way to add one button to the bottom of the typeahead
popup, but it's the only thing that I could think of. So, we will need to only show a button after the last match
. How about ng-if
.
<a>
<span bind-html-unsafe="match.model.label | cmcTicketingTypeaheadFilter"></span>
</a>
<div
ng-if="($parent.$parent.matches.length - 1) === index"
style="border-top:1px solid #DDDDDD;"
>
Example
<button
ng-click="$emit('foo', this)"
class="bt btn-primary"
>
Click To Emit
</button>
</div>
...purposely formatted weird to avoid scroll-bars...
..and this is what I got:
You may be wondering... what the $parent.$parent.matches
thing is all about.
First of all, we are working in the scope
of the Typeahead Directive
.
In this scope
we have three values: match
, index
, and query
. I needed to move up the scope
levels until we reached a parent scope
that had a listing of all returned matches
. Every scope
has the $parent
attribute, showing its parent scope
.
NOW, for your full answer! I am not sure how you plan to access your scope
for your offsetEnd
variables, but I would suggest making it accessible on your matches.
Instead of passing an array of strings
, you can pass an array of objects. This is why my template shows match.model.label
. I used an array of objects where each object was:
{
label: 'Alabama'
value: 0
}
This way I can grab any value I want from a user selection, not just the label. I would suggest placing a value on these options here somewhere and using ng-if
to help you do the matches
paging like you are talking about.
Good Luck! Hope that helped! And dang, as I was typing this up someone posted another answer!
Upvotes: 1