AngularJS - Custom filter not working - angularjs

I want to find the names, starting with the given letter i.e 'm' using angular's custom filter. Here I should get 2 entries in solutions but my view part shows only two bullets of an unordered list and not showing the names that starts with 'm'.
This is my filter:
arg.filter("startwith",function()
{
return function(input,option)
{
var op = [];//var s="";
for(var i=0;i<input.length;i++)
{
if(input[i].sname.charAt(0) == option)
op.push(input[i].sname);
}
// $scope.op;
// s=op.toString();
return op;
}
});
This is controller:
$scope.stud = [
{sid:1,sname:'john',gender:1,type:"fulltime"},
{sid:2,sname:'ashish',gender:1,type:"fulltime"},
{sid:3,sname:'naina',gender:2,type:"parttime"},
{sid:4,sname:'mitesh',gender:3,type:"fulltime"},
{sid:5,sname:'mithila',gender:2,type:"parttime"}
]
This is the view:
<h3> Names Start with M</h3>
<ul>
<li ng-repeat="s in stud | startwith : 'm'">
{{stud.sname}}
</li>
</ul>

It is because in your custom filter you are not returning objects but returning strings therefore the following would return empty as your strings would not have property of sname
<ul>
<li ng-repeat="s in stud | startwith : 'm'">
{{s.sname}}
</li>
</ul>
changing {{s.sname}} line to {{s}} would give you results.
<ul>
<li ng-repeat="s in stud | startwith : 'm'">
{{s}}
</li>
</ul>
Demo

Related

Grabbing value from nested json array with Angular

I'm having trouble accessing the artists array within the items array here to be able to render the name field:
I'm currently able to grab other values at the same level as the artists that are simple objects. How can I loop through the array of the nested array?
Controller
$scope.search = "";
$scope.listLimit = "10";
$scope.selectedSongs = [];
$scope.addItem = function(song){
$scope.selectedSongs.push(song);
}
function fetch() {
$http.get("https://api.spotify.com/v1/search?q=" + $scope.search + "&type=track&limit=50")
.then(function(response) {
console.log(response.data.tracks.items);
$scope.isTheDataLoaded = true;
$scope.details = response.data.tracks.items;
});
}
Template
<div class="col-md-4">
<div class="playlist">
<h3>Top 10 Playlist</h3>
<ul class="songs" ng-repeat="song in selectedSongs track by $index | limitTo: listLimit">
<li><b>{{song.name}}</b></li>
<li>{{song.artists.name}}</li>
<li contenteditable='true'>Click to add note</li>
<li contenteditable='true'>Click to add url for image</li>
</ul>
<div id="result"></div>
</div>
</div>
You should do another ng-repeat to access the artists,
<div class="songs" ng-repeat="song in selectedSongs track by $index | limitTo: listLimit">
<ul ng-repeat="artist in song.artists">
<li><b>{{song.name}}</b></li>
<li>{{artist.name}}</li>
<li contenteditable='true'>Click to add note</li>
<li contenteditable='true'>Click to add url for image</li>
</ul>
</div>

Adding more than one filter is not working for list in Angularjs

I have added 2 filters like uppercase and lowercase for list, data is not displaying . If apply only lowercase or uppercase data is displaying.
Please check the code below and please let me know where is the issue.
<div ng-app="myApp1" ng-controller="ctrl1">
<ul >
<li ng-repeat="x in names | orderBy:'name'">
{{x.name | lowercase +' , '+x.country | uppercase }}
</li>
</ul>
</div>
<script>
var app1= angular.module("myApp1",[]);
app1.controller("ctrl1", function($scope){
$scope.names=[{name:"ravi", country:"india"},{name:"kavitha",country:"india"},
{name:"Jo", country:"UK"},{name:"Hasi", country:"USA"},
{name:"Raj", country:"London"},{name:"Kal", country:"USA"}];
});
</script>
Here list is not populating, if have both uppercase and lowercase filters.
You should write a custom filter instead, if you're gonna be doing something more complex than what's out of the box...
angular.module("MyApp", []).filter("myFilterName", function() {
return function(input) {
if(!input) return "";
else
return input.name.toLower() + input.country.toUpper();
}
});
HTML:
<div ng-repeat="thing in things">
{{ thing | myFilterName }}
</div>
Try this:
angular.module('YourModule').filter('personLocationDisplay', function() {
return function(person) {
return (person.name.toLowerCase() + ', ' + person.country).toUpperCase();
};
});
And you can use it like:
<ul>
<li ng-repeat="x in names | orderBy:'name'">
{{x | personLocationDisplay }}
</li>
</ul>

Angular.js interpolation in filter parameter

I have a filter on a ng-repeat, which accepts a parameter. It currently works with a string.
<div ng-repeat="(key, value) in searchData | aboutFilter:'abo'">
Is is possible to use an interpolated value in place of the string?
<div ng-repeat="(key, value) in searchData | aboutFilter:'{{list.api}}'">
Here is my filter:
app.filter('aboutFilter', function() {
return function(items, input) {
var filtered = [];
angular.forEach(items, function (value,key) {
if(key===input){
filtered.push(value);
}
});
return filtered;
}
});
Here is the complete template logic:
<ul ng-repeat="list in englishList">
<a ng-class="{{list.title}}Hide" mobile-search-slide href="/about"><li><p>{{list.title}}</p><i class="fa fa-chevron-right"></i></li></a>
<ul id="hideMe" ng-class="'hide{{list.title}}'">
<div ng-cloak ng-repeat="(key, value) in searchData | aboutFilter:'{{list.api}}'">
<div ng-repeat="result in value" ng-class-odd="'odd'" ng-class-even="'even'">
<a ng-href="{{value.title}}/{{result.shortname}}">
<li>
<p>{{result.title}}</p><i class="fa fa-chevron-right"></i>
</li>
</a>
</div>
</div>
</li>
</ul>
</ul>
If you want to use some ng-modelfor filter, then you can just use the model name. No need to use {{}} expression.
In your case, it will be :
<div ng-cloak ng-repeat="(key, value) in searchData | aboutFilter:list.api">
DEMO
Remember in your filter, you are using string comparison. So the filter will check for exact matches.
And also, IN your filter:
You are comparing key with the input list.api. Here key will always be 0,1, etc index. You must be using value there instead of key

How to perform an action when a filtered collection changes

I have 3 connected lists that need to work a bit like cascading dropdown lists, that is, selecting an item in the first list filters the second which filters the third.
To achieve this I am using angular filters like so:
<div ng-app="" ng-controller="DemoCtrl">
<h3>Categories</h3>
<ul>
<li ng-repeat="cat in model.categories"
ng-click="selectCategory(cat)"
ng-class="{ active: cat === selectedCategory }">{{ cat }}</li>
</ul>
<h3>Sub Categories</h3>
<ul>
<li
ng-repeat="cat in model.subCategories | filter: { parent:selectedCategory }"
ng-click="selectSubCategory(cat)"
ng-class="{ active: cat.name === selectedSubCategory }">{{ cat.name }}</li>
</ul>
<h3>Products</h3>
<ul>
<li ng-repeat="product in model.products | filter:{ category:selectedSubCategory }">{{ product.name }}</li>
</ul>
</div>
When the top level category changes (selectCategory) I need to ensure that the first sub category is also selected:
$scope.selectCategory = function (cat) {
$scope.selectedCategory = cat;
// how to select the first sub category?
};
Since setting $scope.selectedCategory updates the filtered sub categories, is there anyway I can be notified when the filtered collection changes so I can select the first item ($scope.selectSubCategory)?
http://jsfiddle.net/benfosterdev/dWqhV/
You could set up a watcher on $scope.selectedCategory and manually run $filter to get the first sub-category.
In the end I opted for just performing the filtering in my controller and binding to a "filtered" object on my $scope. When the primary category changed we re-filter the subcategories and select the first item:
$scope.selectCategory = function (cat) {
$scope.model.selectedCategory = cat;
var filtered = $scope.getSubCategoriesOf(cat);
$scope.model.filteredSubCategories = filtered;
$scope.selectSubCategory(filtered[0]);
}
$scope.getSubCategoriesOf = function (cat) {
return $filter('filter')($scope.model.subCategories, { parent: cat }, true);
}

AngularJS - create dynamic filter which changes with each ng-repeat iteration

I have a list of regions, and each region has a drop-down list that should show only the cities in that particular region. I used a nested ng-repeat for this:
<li ng-click="filter_region($event)" ng-repeat="region in regions">
<span>{{region.region}}</span>
<ul class="cityFilter" >
<li ng-repeat="city in cities | filter:cityList">
<input type="checkbox" value="{{city.id}}" ng-model="city.checked" ng-checked="city.checked">
<span>{{city.city}}</span>
</li>
</ul>
</li>
I need cityList as a dynamic filter. Each city should be filtered based on the current region.
i.e. the region value needs to change with each iteration of the outer loop
pseudo-code for the filter:
$scope.cityList = function (item) {
if (item.region_id == myDynamicRegion)
return true;
return false;
}
Is it doable?
Yes, it is doable. You can pass arguments to your filter:
<div ng-repeat="item in items |filter:x"></div>
And the filter:
yourApp.filter('filter', function () {
return function (item, x) {
// Do the magic.
};
});

Resources