"Contains" search for a sub-element of an object array - angularjs

Here's my data:
[
{profile: {name: "Test123"}}
]
I have a text input, like so:
<input ng-model="searchText">
I'm trying to do a search on profile.name using the textbox input.
I've tried making a custom filter, like so:
$scope.searchFilter = function(value){
return value.profile.name.indexOf($scope.searchText) != -1;
};
Then filtering like so:
<tr ng-repeat="profile in profiles | filter: searchFilter"></tr>
It seems unfortunately that this works fine on the initial search, but when entering text into the textbox the filter is not re-evaluated.
How can I force Angular to re-check the filter when I enter text into the search box, or is there a better way to do this?

You don't need to create a function to search. Just change your html into this:
<input ng-model="searchText.profile.name" />
...
<tr ng-repeat="data in profiles | filter: searchText">{{data.profile.name}}</tr>
In your controller:
$scope.searchText = { profile: {name:""}}; //should be the same data struct with your search target.
$scope.profiles = [
{profile: {name: "Someone"}},
{profile: {name: "Luky"}},
{profile: {name: "John"}},
{profile: {name: "Mary"}},
{profile: {name: "Howard"}},
{profile: {name: "Sheldon"}}
]
Then it works. Here is jsfiddle. : )
And here is filter document.

Related

How to hide element if object in array is missing field

So I have an html element like this:
<div ng-hide="!myarr.length">
Im showing
</div>
Somewhere else an array is populated.
Before it is being populated it will not have a length, so the div above will not show up.
However, when the array will be filled with data (json objects) I need to understand if all the objects in the array contain a specific field (and it cannot be empty).
So my json could eventually look like this:
myarr[0] = {name: 'jack', type: ''}
myarr[1] = {name: 'jack'}
myarr[2] = {name: 'jack', type: 'mytype'}
In the case above, the div should continue to be hiding as not all the json objects contain a "type"-field that is not empty.
How do I accomplish this?
I was thinking to have an OR statement in the ng-hide. Maybe I could use the "some"-function. But when doing this it seems I cannot run this kind of function inside the ng-hide (at least my editor marks the code with red). Is there an alterntive way to do this without needing to call a function in my controller?
When you retrieve the data, you can iterate over each object in the array and examine the individual objects. If any individual object DOES NOT contain the necessary data, set the display flag to false and break out of the loop.
$scope.showElement = true;
$scope.array = [
{name: 'jack', type: ''},
{name: 'jack'}
{name: 'jack', type: 'mytype'}
];
for(let i=0; i<$scope.array.length; i++){
if($scope.array[i].type === undefined || $scope.array[i].type === ''){
$scope.showElement = false;
break;
}
}

Angular - Filtering an ng-repeat by Item.User._id

Im trying to filter an ng-repeat by an id value.
$scope.filter = $stateParams.id; --> 56a1832a36dc3d0e00c7aa3f
Heres the model for the Item Object with relevant vlues
var ItemSchema = new Schema({
title: {
type: String,
maxlength: 150
}
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
How exactly do i filter the Items by the user._id ?
My attempt which is giving no results.
<div ng-repeat="saving in savings| filter: {user : 'filter'}">
https://plnkr.co/edit/sihBuRe9vNKO0jB1Wk8b
The docs explain using filters very well. The filter filters the array by property you pass to it. If it's an object, it will match its properties against each item in the array. This means that item in array with property user: {_id: 2} will be shown.
<div ng-repeat="saving in savings | filter:{user: {_id: 2}}">{{saving.title}}</div>
You can checkout this question for another example.

AngularJS filter based on the column displayed

Please refer to this Plunk: http://plnkr.co/edit/5YCCdDSnpHKRU51R9vCL?p=preview
How do I filter based on the field that is displayed? Currently, the filtering is done on the complete user object.
For eg:
$scope.users1 = [
{name: 'Dave', id: 24},
{name: 'Tim', id: 22},
{name: 'Laura', id: 20}
];
<user-info-card users="users" label="name">
</user-info-card>
If I display only the id, the filter works even if I type "Dave". I want it to work only on the fields displayed. Also want it to be generic. It could be a different object but the search term should look at the label field and filter accordingly
Added a function which will sort based on label, hope if suffice.
http://plnkr.co/edit/iCepagIKA1OFDjBnB35I?p=preview
$scope.searchTerm = function(item) {
if(item[$scope.label].toString().
startsWith($scope.searchCondition1)){
return true;
}
else{
return false;
}
}
You can use strict filter to do this stuff.
test.html
<div>
<input placeholder="Search for a name..." ng-model="searchTerm" ng-change="onChange()">
<div ng-repeat="user in users | filter:user:strict">
...
</div>
</div>
During text box key change event, search term is converted as object field value.
script.js
$scope.onChange = function () {
var user = {};
user[$scope.label] = $scope.searchTerm;
$scope.user = user;
};
Check this link

ng-options not working as expected

I'm having an issue trying to loop through an array of objects using ng-options.
html
<select class="select-width" ng-options="type as type.name for type in types">
js
$scope.types = [{name: "Advanced Yield Analysis"},
{name: "Yield by Hybrid"},
{name: "Yield by planting data"},
{name: "Yield by soil type"},
{name: "Yield by management zone"},
{name: "Yield by population/seeding rate"},
{name: "Yield by Treatment"},
{name: "Total Yield by Grower / Location / MC"}];
Here is a JS-fiddle.
You only need to pass the ng-model. Ng-options will not work when you're not assigning a model.
By default, ngModel watches the model by reference, not value. This is
important when binding any input directive to a model that is an
object or a collection.
try
<select class="select-width" ng-model="demo" ng-options="type as type.name for type in types"></select>
Fiddle

declaring two object literals in (one?) data-ng-init and binding them to different views

I'm trying to create two different object literals and bind them to different views (<table>s). However, I'm not sure how to go about doing this. I've tried the below method where I declare both object literals in one data-ng-init of a parent container (the div). I've also tried having two different data-ng-init directives for that div and having one object literal in each of the directives. However both methods did not work and I get errors (will post if anyone would like to see them).
Example of what I've tried:
<div id="recipes" data-ng-init="
dessertsdrinks = [
{name: 'Apple Pie Popcorn', url: 'pdfs/recipes/desserts_and_drinks/Apple Pie Popcorn.pdf'},
{name: 'Zucchini Muffins', url: 'pdfs/recipes/Zucchini Muffins.pdf'}
];
maineats = [
{name: 'Autumn Enchilada Casserole', url: 'pdfs/recipes/Autumn Enchilada Casserole.pdf'},
{name: 'Build your own Taco', url: 'pdfs/recipes/Build your own Taco.pdf'},]
">
<table id="dessertsdrinks">
<th>Desserts and Drinks</th>
<tr data-ng-repeat="recipe in dessertsdrinks | filter:recipesearch | orderBy:'name'">
<td> {{ recipe.name }} </td>
</tr>
</table>
<table id="maineats">
<th>Main Eats</th>
<tr data-ng-repeat="recipe in maineats | filter:recipesearch | orderBy:'name'">
<td> {{ recipe.name }} </td>
</tr>
</table>
</div>
When I only have one object literal and one data-ng-init it works perfectly.
But how could I do this with two different lists? Is there a better way?
For example, could I have a controller which binds object literals to $scope based on the view's (table's) id tag or something? Like so :
psuedocode
function recipeController(){
if $scope id == "desertsdrinks" {
$scope.recipes = [{.. dessert and drink recipe obj literal ..}];
} else if $scope id == "maineats" {
$scope.recipes =[{.. main eats recipe obj literal..}];
}
}
Simply moving the objects inside the controller should work:
$scope.dessertsdrinks = [
{name: 'Apple Pie Popcorn', url: 'pdfs/recipes/desserts_and_drinks/Apple Pie Popcorn.pdf'},
{name: 'Zucchini Muffins', url: 'pdfs/recipes/Zucchini Muffins.pdf'}
];
$scope.maineats = [
{name: 'Autumn Enchilada Casserole', url: 'pdfs/recipes/Autumn Enchilada Casserole.pdf'},
{name: 'Build your own Taco', url: 'pdfs/recipes/Build your own Taco.pdf'}
]
No need to change the way you access them inside the html.
You can also pass an object literal directly into the ng-init directive. Each property (name is up to you) value will be evaluated and main avaialble on the scope.
ng-init="{a: dessertDrinks = [...], b: maineats = [...]}"

Resources