I want to put 2 customs filters on a data. Each filter is working perfectly independently, but when I put the 2 on the same data, I have an error message (TypeError: input.replace is not a function), but if I comment this, I have another error message (Error: [$sce:itype] Attempted to trust a non-string value in a content requiring a string: Context: html)
The 2 customs filters are goBold which take no argument, and limitHellip which takes the maximum length of the string as an argument.
thanks a lot, here is the code :
angular.module('appFilters', []).
filter('goBold', function($sce) {
return function (input) {
input = input.replace(' filter ',' <strong>WORD FILTERED</strong> ');
return $sce.trustAsHtml( input );
}
}).
filter('limitHellip', function($sce) {
return function (input, limit) {
console.log(limit);
if( input.length > 100 ) {
input = input.substring(0,100);
var index = input.lastIndexOf(" ");
input = input.substring(0,index) + "…";
}
return $sce.trustAsHtml( input );
}
});
<ion-content class="has-subheader">
<ion-item class="element item item-divider" data-ng-repeat="item in blocInfos" >
<a href="#/list/{{ item.url }}">
<img data-ng-src="img/{{ item.imageUrl }}" alt="">
<h2 class="title">{{ item.title }}</h2>
</a>
<p data-ng-bind-html="item.text | limitHellip: 100 | goBold" class="wrap"></p>
</ion-item>
</ion-content>
This is because your first filter return an $sce.trusAsHtml() which is an Object and not a string so you can't call the replace() method.
So, you have to change it into a String
Plunkr
Filters
angular.module('appFilters', []).
filter('goBold', function($sce) {
return function (input) {
input = input.toString(); //This line was added
input = input.replace(' filter ',' <strong>WORD FILTERED</strong> ');
return $sce.trustAsHtml( input );
}
}).
filter('limitHellip', function($sce) {
return function (input, limit) {
input = input.toString(); //Maybe you have to add it here too
console.log(limit);
if( input.length > limit ) {
input = input.substring(0,limit);
var index = input.lastIndexOf(" ");
input = input.substring(0,index) + "…";
}
return $sce.trustAsHtml( input );
}
})
Related
I have a little problem, I would like to do a equals with 2 var in ngFilter. I try lot of combinaison, but it doesn't work...
I get the first var here, in $routeParams
function ANNAnnonceListe(DBManager, $routeParams) {
var ici = this;
this.annonces_ar = [];
this.idLieu = $routeParams.idLieu;
DBManager.all('ANNAnnonce')
.then(function (annonces) {
console.log(annonces);
ici.annonces_ar = annonces;
})
.catch(function (error) {
console.log(error)
});
}
the second here :
<div ng-repeat="(key, value) in vm.annonces_ar | filter: {value.id : vm.idLieu_nb} ">
{{value.nom_str}}
{{value.idLieu_nb}}
</div>
i would like this equality (vm.idLieu = value.id_nb) and display if is true
Thanks.
It should be property name directly id_nb instead of value.id. Also have : true parameter at the end of your filter to perform exact check, inspite of contains check.
<div ng-repeat="(key, value) in vm.annonces_ar | filter: { idLieu_nb : vm.idLieu}: true ">
{{value.nom_str}}
{{value.idLieu_nb}}
</div>
searchStr is user input search keyword , once i rendered response from server i want to highlight user input searchStr so user can see what is being searched and compare if its part of response. So below code is highlighting whole string response from server in my case i just want to highlight searched string that will be part of response.
Lets assume i have string
info|<n/a>|[routes.event] ########## Message added to processing queue ########## e63637db-aa33-4aed-b5b0-51a0764dc7f1 { workerId: 3, pid: 33029 } and i want to highlight e63637db-aa33-4aed-b5b0-51a0764dc7f1 _id that will be searchStr
main.html
<tr ng-repeat="item in showMessages | filter:searchStr" >
<td >{{item.filename}}</td>
<td class="serverResults" ng-bind-html="item.value | trusted">{{item.value}}</td>
</tr>
ctrl.js
$scope.$on('displaySearchResults',function(e,data){
$scope.searchStr = data.searchStr;
$scope.showMessages = data.messageObj;
})
filters.js
angular.module('App').filter('trusted', ['$sce', function ($sce) {
return function(text,phrase) {
if (phrase) text = text.replace(new RegExp('('+phrase+')', 'gi'),
'<span class="highlighted">$1</span>');
var content = text.toString()
console.log('Content',content);
var data = content.replace(/[|&;$%#"<>()+,]/g, "");
return $sce.trustAsResourceUrl(data);
};
}]);
Here is a working sample to show how you might accomplish the highlighting. It is contrived because I'm just creating an array with a single item, but it illustrates the approach. You want to apply your replacement of reserved characters first because if you apply that after you have inserted the highlighted <span> the < and > characters will be stripped by your replacement regex.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.showMessages = [{
value: 'info|<n/a>|[routes.event] ########## Message added to processing queue ########## e63637db-aa33-4aed-b5b0-51a0764dc7f1 { workerId: 3, pid: 33029 }'
}];
$scope.searchStr = 'e63637db-aa33-4aed-b5b0-51a0764dc7f1';
})
.filter('trusted', function($sce) {
return function(text, phrase) {
if (phrase) {
var data = text.replace(/[|&;$%#"<>()+,]/g, "");
data = data.replace(new RegExp('(' + phrase + ')', 'gi'),
'<span class="highlighted">$1</span>');
return $sce.trustAsHtml(data);
}
text = text.replace(/[|&;$%#"<>()+,]/g, "");
return $sce.trustAsHtml(text);
};
});
.highlighted {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div>Search: <input type="text" ng-model="searchStr" /></div>
<div>
<table>
<tr ng-repeat="item in showMessages | filter:searchStr">
<td>{{item.filename}}</td>
<td class="serverResults" ng-bind-html="item.value | trusted:searchStr"></td>
</tr>
</table>
</div>
</div>
http://jsfiddle.net/f4Zkm/213/
HTML
<div ng-app>
<div ng-controller="MyController">
<input type="search" ng-model="search" placeholder="Search...">
<ul>
<li ng-repeat="name in names | filter:filterBySearch">
{{ name }}
</li>
</ul>
</div>
</div>
app.js
function escapeRegExp(string){
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function MyController($scope) {
$scope.names = [
'Lolita Dipietro',
'Annice Guernsey',
'Gerri Rall',
'Ginette Pinales',
'Lon Rondon',
'Jennine Marcos',
'Roxann Hooser',
'Brendon Loth',
'Ilda Bogdan',
'Jani Fan',
'Grace Soller',
'Everette Costantino',
'Andy Hume',
'Omar Davie',
'Jerrica Hillery',
'Charline Cogar',
'Melda Diorio',
'Rita Abbott',
'Setsuko Minger',
'Aretha Paige'];
$scope.search = '';
var regex;
$scope.$watch('search', function (value) {
regex = new RegExp('\\b' + escapeRegExp(value), 'i');
});
$scope.filterBySearch = function(name) {
if (!$scope.search) return true;
return regex.test(name);
};
}
From the above example, I have been trying to create a wildcard regex search by using a special character '*' but I haven't been able to loop through the array.
Current output: If the input is di, it showing all the related matches.
Required: What I am trying to get is, if the input is di*/*(any input), it should show all the matches as per the given input.
There are a couple issues with your approach. First, you are escaping * in your escape routine, so it can not be used by the client.
Second, you are not anchoring your lines, so the match can occur anywhere.
To fix, remove the asterisk from the escape function :
function escapeRegExp(string){
return string.replace(/([.+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
Then in your watch function replace * with .* and add line anchors :
$scope.$watch('search', function (value) {
var escaped = escapeRegExp(value);
var formatted = escaped.replace('*', '.*')
if(formatted.indexOf('*') === -1){
formatted = '.*' + formatted + '.*'
}
regex = new RegExp('^' + formatted + '$', 'im');
});
Here is a fiddle
I have the following scope and if this is greater than 5, I'd like to display something like 'more than ten items' otherwise it will just list the items in a human readable list
<span class="bold-words">{{rule.words.join(', ')}}</span>
What is the correct AngularJS way to do this?
e.g so it would show like below
// less than 5
Your list is "peas, fruit, tea"
// more than 5
Your list is greater than 5 items
You can do it easily with ternary operator
<span class="bold-words">Your list is {{ rule.words.length > 5 ? 'greater than 5 items' : rule.words.join(', ') }}</span>
try something like this ...
<span class="bold-words">Your list is {{(rule.words.length>5)?'greater than 5 item':(rule.words.join(', '))}}</span>
I would prefer a filter like {{ rule.words | beautifier:5 }} So you can use it on different cases and can modify your output at will. See the snippet for a working example:
var app = angular.module('bar', []);
app.controller('foo', function($scope) {
$scope.bar = ['asdasd', 'egeg', 'hjgkj', 'adaa'];
});
app.filter('beautifier', function() {
return function(input, count) {
var output;
if (input.length > count) {
output = 'Your list is greater than ' + count +' items.';
} else {
output = 'Your list is "' + input.join('", "') + '"';
}
return output;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="bar">
<div ng-controller="foo">
<p>{{ bar | beautifier:5 }}</p>
<p>{{ bar | beautifier:3 }}</p>
</div>
</div>
I want want to display and count only batter in batters at index 0.
i.e id = 1001 type = regular
and count should be "4"
Maybe this updated JSFiddle will give you an idea.
HTML
<div ng-app="myApp" ng-controller="customersCtrl">
<ul ng-repeat="x in myData">
<li ng-repeat = "batter in x.batters.batter | filter: {'id': 1001, 'type': 'Regular'}">
{{ batter.id }} - {{ batter.type }}
</li>
</ul>
{{countBatters(1001, 'Regular')}}
</div>
Added function in controller:
$scope.countBatters = function(id, type) {
return $scope.myData.filter(function(obj) {
var batter = obj.batters.batter[0];
return batter.id == id && batter.type == type
}).length;
}
Use array filter method..
var getBatter1001 = (item) => { return item.batters.batter.filter((x) => {x.id === '1001'}); }
var batter1001 = $scope.myData.filter(getBatter1001);
console.log('Count of objects with batter id 1001: '+batter1001.length); // Logs 3