好吧,我有plunkr试图模拟我的情况:
这个想法是用户在文本框中键入一个单词,当单击该按钮时,角度服务会根据文本框中的类型从DB返回答案(结果)(我已经通过请求数据模拟了此过程)到一个json文件,所以无论你键入什么都不重要,总是会返回整个数据)并填充一个表。
但是现在,我正在使用过滤搜索。在此文本框中,您可以搜索由以下人员定义的人员:
我实现了两种可视化过滤器:
1)隐藏和显示结果的可视化过滤器:(在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)用于突出显示结果的可视过滤器:(在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'
}
};
});
调用这些过滤器的html :(在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>
但我遇到了一些问题,因为有时候这个人没有中间名,或者有时候没有第二名。
要重现我的问题,请在搜索框中输入: Lora ,然后将其删除,您会看到某些数据未以正确方式呈现。如果您输入 Loras 并删除 s ,则该字词不会再次突出显示,但如果您继续删除,则会再次突出显示该字词。
那么,我做错了什么?我认为这是$scope.changeValue
过滤器的问题,但我输了。
有什么想法吗?
答案 0 :(得分:2)
我相信你遇到的问题是在你的highLight指令中。 它试图修改其内容,并假设其内容是什么......
element[0].cells[i].innerHTML = element[0].cells[i].innerText.replace(regex, replacer);
实际上问题在于时机问题。 highLight指令有时会在插值发生之前修改HTML。所以你最终得到的东西是:
<td class="ng-binding">{{expense.first_name}} {{expense.midd<span class="angular-highlight">l</span>e_name}}</td>
显然Angular不明白。
答案 1 :(得分:1)
Angular似乎是一个悬而未决的问题 - https://github.com/angular/angular.js/issues/11716
如果您使用ng-bind
更改了 <td><span ng-bind="expense.first_name"></span><span ng-bind="expense.middle_name"></span></td>
<td><span ng-bind="expense.first_surname"></span><span ng-bind="expense.second_surname"></span></td>
<td><span ng-bind="expense.age"></span></td>
绑定,则过滤功能会按预期进行 -
----- UPDATE - Jan,4, 2016 -----
ng-bind
我还没找到一个令人满意的解释。这种行为似乎与$watch
用于{{ }}
事物以及$observe
用于ng-bind
的方式有关,我不太确定。
根据角度最佳做法 - https://github.com/angular/angular.js/blob/2a156c2d7ec825ff184480de9aac4b0d7fbd5275/src/ng/directive/ngBind.js#L16,scope
是绑定$observer
中值的首选方法,除非这些是DOM属性,在这种情况下,您可以{{ }}
指令中的属性。参考 - AngularJS : Difference between the $observe and $watch methods
另一个区别 - 与$digest
相比,ng-bind
观察者会被$watch
点燃,ng-bind
----- UPDATE - Jan,5, 2016 -----
float
padding
.bottomItem {
display: flex;
flex-direction: row;
align-items: center;
margin: 10px;
}
.right {
max-width: 60%;
margin: 0 10px;
}
更好,即使你最终写了更多的HTML。参考 - AngularJS : Why ng-bind is better than {{}} in angular?
<div id="bottomPanel">
<div class="bottomItem">
<img src="http://placehold.it/150x150">
<div class="right">
<a href="#" title="description" class="item_bottomDesc">Lorem ipsum dolor sit amet</a>
<p class="item_bottomAbout">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur gravida, massa ut suscipit suscipit, massa elit sollicitudin eros, nec lacinia neque odio a est. Phasellus tincidunt nulla eget lorem sodales</p>
</div>
</div>
<div class="bottomItem">
<img src="http://placehold.it/150x150">
<div class="right">
<a href="#" title="description" class="item_bottomDesc">Lorem ipsum dolor sit amet</a>
<p class="item_bottomAbout">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur gravida, massa ut suscipit suscipit, massa elit sollicitudin eros, nec lacinia neque odio a est. Phasellus tincidunt nulla eget lorem sodales</p>
</div>
</div>
<div class="bottomItem">
<img src="http://placehold.it/150x150">
<div class="right">
<a href="#" title="description" class="item_bottomDesc">Lorem ipsum dolor sit amet</a>
<p class="item_bottomAbout">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur gravida, massa ut suscipit suscipit, massa elit sollicitudin eros, nec lacinia neque odio a est. Phasellus tincidunt nulla eget lorem sodales</p>
</div>
</div>
</div
正确答案见Pete BD
答案 2 :(得分:0)
嗯,根据 FrailWords 和 PeteBD 的优秀答案,我有了一个想法,现在有效!
诀窍在于 插值 。检查the docs并找到优秀的fiddle,解决方案使用$interpolate
和$eval
使用non isolated scope
。
var interpolation = $interpolate(element[0].cells[i].innerText);
element[0].cells[i].innerHTML = scope.$eval(interpolation).replace(regex, replacer);
整个指令的代码:
app.directive('highLight', ['$interpolate', function ($interpolate) {
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(attrs.highLight, 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++){
var interpolation = $interpolate(element[0].cells[i].innerText);
element[0].cells[i].innerHTML = scope.$eval(interpolation).replace(regex, replacer);
}
}
});
}
return {
link: component,
replace: false
};
}]);
html总是这样:
<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>
现在一切都像魅力一样。太棒了,但真的是。