I have created a plunkr to demonstrate my current situation:
The user is required to type a word into the textbox, and upon clicking the button, an angular service retrieves data from a DB based on the input text. The retrieved data is then displayed in a table.
I am currently working on implementing a filter search. The search can be performed on a person's information such as:
- first_name
- middle_name
- first_surname
- second_surname
I have incorporated two visual filters:
1) Visual Filter for hiding and showing results: (defined in appCtrl.js)
$scope.changedValue=function(){
var condition = $scope.filter.condition;
$scope.Model.filteredlist = filterFilter($scope.Model.expenses,function(value, index, array){
var fullname = (value.first_name+' '+value.middle_name+' '+value.first_surname+' '+value.second_surname).toLowerCase();
if (fullname.indexOf(condition.replace(/\s\s+/g, ' ').toLowerCase()) > -1 ) {
return array;
}
});
if (typeof $scope.Model.filteredlist != 'undefined') { // When page loads for first time
$scope.setPage();
}
}
2) Visual Filter for highlighting the results: (defined in appDrct.js)
app.directive('highLight', function ($document, $sce) {
var component = function(scope, element, attrs) {
if (!attrs.highlightClass) {
attrs.highlightClass = 'angular-highlight';
}
var replacer = function(match, item) {
return '<span class="'+attrs.highlightClass+'">'+match+'</span>';
}
var tokenize = function(keywords) {
keywords = keywords.replace(new RegExp(',$','g'), '').split(' ');
var i;
var l = keywords.length;
for (i=0;i<l;i++) {
keywords[i] = keywords[i].replace(new RegExp('^ | $','g'), '');
}
return keywords;
}
scope.$watch('keywords', function(newValue, oldValue) {
console.log("new: " + newValue + " old " + oldValue);
var tokenized = tokenize(newValue);
var regex = new RegExp(tokenized.join('|'), 'gmi');
if(newValue.length>=1 || oldValue.length>=1){
for(i=0;i<=1;i++){
element[0].cells[i].innerHTML = element[0].cells[i].innerText.replace(regex, replacer);
}
}
});
}
return {
link: component,
replace: false,
scope: {
keywords: '=highLight'
}
};
});
The html calling those filters: (defined in table.html)
<input type="text" class="form-control" id="filter-list" placeholder="Name(s) and/or Lastname(s)" ng-model="filter.condition" ng-change="changedValue()">
......
<tr ng-repeat="expense in Model.filteredlist | pagination: pagination.currentPage : numPerPage" x-high:light="filter.condition">
<td>{{expense.first_name}} {{expense.middle_name}}</td>
<td>{{expense.first_surname}} {{expense.second_surname}}</td>
<td>{{expense.age}}</td>
</tr>
However, I encountered some issues where certain data is not rendered correctly when there are missing values for middle_name or second_surname.
To replicate the issue, enter "Lora" in the search box, then delete it. You will notice that some data is not displayed correctly. Also, if you type "Loras" and then erase the "s", the word does not highlight again until you continue erasing characters.
I suspect the issue lies within the $scope.changeValue filter, but I'm unsure of how to resolve it.
Any suggestions or ideas?