Angularjs filter part of name - angularjs

I have a jsFiddle here - http://jsfiddle.net/GRw64/
I'm new to Angularjs so still finding my feet
My example is a simple ng-init of customer names.
An input field and a ng-repeat to filter the name in the input field against the customer names.
If you type a name in the input field the ng-repeat filters the list to show that name.
If I type Chris the name 'Chris Dave' and 'Chris' appear in the list.
If I change to 'Chris Dave', 'Chris Dave' is still showing in the list but 'Chris' disappears
How can I get a return with all the results that match at least one word in the search.
<!doctype html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.2.6/angular.min.js"></script>
</head>
<body ng-app="" data-ng-init="customers=[{name:'Chris Dave'},{name:'Chris'},{name:'John'},{name:'Paul'}]">
<div class="container">
Names:
<br />
<input type="text" data-ng-model="name" />
<br />
<ul>
<li data-ng-repeat="cust in customers | filter:name">{{ cust.name }}</li>
</ul>
</div>
</body>
</html>

You can also provide a function to the filter filter of Angular:
ng-repeat="cust in customers | filter:filterByName"
Then you have to define the function in your controller:
$scope.filterByName = function(customer) {
if(!$scope.name) {
return true;
} else {
var keywords = $scope.name.toLowerCase().split(' ');
for(var i in keywords){
var k = keywords[i];
if (customer.name.toLowerCase().indexOf(k) >= 0) {
return true;
}
}
return false;
}
}
Working example

Suppose you treat the space-separated keywords as OR relationship, you can create a custom filter to achieve what you need like this:
var app = angular.module('myApp', []);
app.filter('myFilter', function () {
return function (names, keyword) {
var listToReturn = [];
if (keyword === undefined) return names;
var keywords = keyword.toLowerCase().split(' ');
angular.forEach(names, function (name) {
for(var i in keywords){
var k = keywords[i];
if (name.name.toLowerCase().indexOf(k) >= 0) {
listToReturn.push(name);
break;
}
}
});
return listToReturn;
};
});
DEMO

Related

Angular custom search filter

I need to create a custom search filter for this scope. I tried the default filter function , doesn't works, Because I displayed status as string in HTML and it is not filtered the way I want it. If I type Normal in the textbox, nothing happens because the data is 0, 1 and 2. And if I search the purchase time which is in 2016/05/16 format cannot search also.
$scope.orderHistory = {[
"purchaseTime": 1437536718345,
"status": 1,
]};
app.filter('filterSearch', function () {
//what to do here??
});
<input type="text" ng-model="searchReview">
<div dir-paginate="order in orderHistory|filterSearch:searchReview">
<ul>
<li><p class="table-data2-h">{{ order.purchaseTime | date : 'yyyy/MM/dd'}} </p></li>
<li>
<span ng-if="order.status == 0 ">Stable</span>
<span ng-if="order.status == 1 ">Normal</span>
<span ng-if="order.status == 2 ">Serious</span>
</li>
</div>
At first, I saw some mistakes on your code, you can compare it below.
I'd suggest you to create a simple function to parse your properties accordingly your requirements only on initilization (which one for sure will be better to parse everytime when than custom filter is called), then you can use the normal filter.
See it working:
(function() {
'use strict';
angular
.module('app', [])
.constant('STATUS', {
0: 'Stable',
1: 'Normal',
2: 'Serious'
})
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', 'STATUS'];
function MainCtrl($scope, STATUS) {
$scope.orderHistory = [
{
"purchaseTime": 1437536718345,
"status": 1
},
{
"purchaseTime": 1431236718345,
"status": 0
},
{
"purchaseTime": 1099536718345,
"status": 2
},
{
"purchaseTime": 1439744718345,
"status": 1
}
];
function parseProperties() {
$scope.orderHistory.map(function(order) {
// You can do it with switch statement
// switch (order.status) {
// case 0:
// order.status = 'Stable';
// break;
// case 1:
// order.status = 'Normal';
// break;
// case 2:
// order.status = 'Serious';
// break;
// }
// or using a constant that you can define above
order.status = STATUS[order.status];
order.purchaseTime = new Date(order.purchaseTime).toLocaleDateString();
return order;
});
}
parseProperties();
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<input type="text" placeholder="Search..." ng-model="searchReview">
<div ng-repeat="order in orderHistory | filter: searchReview">
<ul>
<li>
<p class="table-data2-h" ng-bind="order.purchaseTime"></p>
</li>
<li ng-bind="order.status"></li>
</ul>
</div>
</body>
</html>
I hope it helps

Searching a map and retrieving key if matching -angular js

Angular-JS
Searching a map and retrieving key if matching with the user given input key
my map luks like this
var myMap=
{
k:1000,
l:100000,
m:1000000,
c:10000000
};
If user input is "l" , i want to search the map and retrieve l along with value "100000"
and do some further operation
As myMap is an object (aka associative array, aka hash) you can access a value using the
[] operator.
angular.module('MyModule', [])
.controller('MyController', function($scope) {
$scope.myMap = { k:1000, l:100000, m:1000000, c:10000000 };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='MyModule' ng-controller='MyController'>
<input type='text' ng-model='myMapKey' />
<p>myMap value = {{myMap[myMapKey]}}</p>
</div>
To extend the answer from Gruff Bunny, you can also do the following to search for the key-value pair and do your calculation inside the controller and get the result as an output.
angular.module('MyModule', [])
.controller('MyController', function($scope) {
$scope.myMap = { k:1000, l:100000, m:1000000, c:10000000 };
$scope.chkIt = function(myIns){
var myVal = $scope.myMap[myIns];
if(myVal){
//do your calculation here
$scope.myResult = 'Calculation Done | Key: '+myIns+' | Value: '+myVal;
}else{
$scope.myResult = 'No Match for key: '+myIns;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='MyModule' ng-controller='MyController'>
<input type='text' ng-change="chkIt(myMapKey)" ng-model='myMapKey' />
<p>myMap value = {{myResult}}</p>
</div>

How to set first item as default select

I am new to angular.js. I am using list of users with sorter list, when I click the user name the selected user phone number should display in the selected area. It is working fine.
My question is how to I set the first user as default select. here is my sample code. Please help me on this.
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Example</title>
<script src="js/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<h1>Selected View</h1>
<ul>
<li ng-repeat="userNames in users | orderBy:orderProp:direction" ng:click="select(userNames)">{{userNames.name}}</li>
</ul>
<p>selected: {{selectedUser.phone}}</p>
<script>
var myApp = angular.module('myApp', []);
//myApp.by.id('setbtn')element('h1').addClass('active');
myApp.controller('MainCtrl', ['$scope', function ($scope) {
$scope.users = [{name:'John', phone:'555-1276'},
{name:'John', phone:'555-1278'},
{name:'Mary', phone:'800-BIG-MARY'},
{name:'Mike', phone:'555-4321'},
{name:'Adam', phone:'555-5678'},
{name:'Julie', phone:'555-8765'},
{name:'Juliette', phone:'555-5678'}];
//sorting
$scope.direction = false;
$scope.orderProp = "name";
$scope.sort = function(column) {
if ($scope.orderProp === column) {
$scope.direction = !$scope.direction;
} else {
$scope.orderProp = column;
$scope.direction = false;
}
};
//selected list
$scope.select = function(phone) {
$scope.selectedUser = phone;
};
}]);
</script>
</body>
</html>
Just use this in the controller to sets the default user's phone number
$scope.selectedUser = $scope.users[0];
Since the users in a JS Object, instead of a native datatype, the initial selection often causes a problem.
You'll be better off to refactor the select options to use an array of strings rather than an array of Objects.
It is covered in detail in this post.
Hope this helps!
You can sort users from controller instead of html
HTML
<li ng-repeat="userNames in getSortedUsers()"
ng:click="select(userNames)">{{userNames.name}}</li>
Controller
$scope.getSortedUsers = function () {
// Use $filter service. You have to add $filter as dependencies in controller
var users = $filter('orderBy')($scope.users, $scope.orderProp +
':' + $scope.direction);
// Set first user as selected user
$scope.selectedUser = users[0];
return users;
}

ng-options displays blank selected option, even though ng-model is defined

I have created a plunkr to emphasize the problem, perhaps it's because the source of the ng-repeat is a function, I am not sure, but so far I've tried everything in order to solve this, and couldn't mange.
plunkr:
http://plnkr.co/edit/qQFsRM?p=preview
HTML
<html>
<head>
<script data-require="angular.js#1.2.0-rc1" data-semver="1.2.0-rc1" src="http://code.angularjs.org/1.2.0rc1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app='myApp' ng-controller='mainCtrl'>
<ng-include src="'menu.html'">
</ng-include>
</html>
Script
var app = angular.module('myApp', []);
app.controller('mainCtrl', function($scope, $httpBackend){
$scope.model = {};
$scope.model.myJobs = {};
$scope.refreshJobs = function(){
}
});
app.controller('menuCtrl', function($scope){
$scope.model.locations = function(){
var loc = [];
loc[1] = 'Dublin';
loc[2] = 'Stockholm';
loc[3] = 'New Jersy';
$scope.model.selectedLocationDef = loc.indexOf('Dublin');
return loc;
}
$scope.model.selectedLocation = $scope.model.selectedLocationDef;
$scope.$watch('model.selectedLocation', function(location){
$scope.refreshJobs(location);
});
});
If you use an array as model, then the model is a string not a number. So you need to convert the number to string. Just try
$scope.model.selectedLocation = '1';
Last I checked, Angular does not support the ability to bind array keys to ng-model via ng-options. You can, however, mimic this behavior using an object hash:
menu.html:
<div ng-controller="menuCtrl">
<select ng-model="model.selectedLocation" ng-options="x.value as x.label for x in model.locations()">
</select>
</div>
script.js:
$scope.model.locations = function(){
var loc = [{
value: 0,
label: 'Dublin'
}, {
value: 1,
label: 'Stockholm'
}, {
value: 2,
label: 'New Jersey'
}];
$scope.model.selectedLocation = 1; // Set default value
return loc;
}
Bear in mind that this will bind the integers to your model, and not the cities themselves. If you want your model value to be Dublin, Stockholm, or New Jersey, simply do:
menu.html:
<div ng-controller="menuCtrl">
<select ng-model="model.selectedLocation" ng-options="name for name in model.locations()">
</select>
</div>
script.js:
$scope.model.locations = function(){
var loc = ['Dublin', 'Stockholm', 'New Jersey'];
$scope.model.selectedLocation = 'Dublin'; // Set default value
return loc;
}

How to remove elements/nodes from angular.js array

I am trying to remove elements from the array $scope.items so that items are removed in the view ng-repeat="item in items"
Just for demonstrative purposes here is some code:
for(i=0;i<$scope.items.length;i++){
if($scope.items[i].name == 'ted'){
$scope.items.shift();
}
}
I want to remove the 1st element from the view if there is the name ted right? It works fine, but the view reloads all the elements. Because all the array keys have shifted. This is creating unnecessary lag in the mobile app I am creating..
Anyone have an solutions to this problem?
There is no rocket science in deleting items from array. To delete items from any array you need to use splice: $scope.items.splice(index, 1);. Here is an example:
HTML
<!DOCTYPE html>
<html data-ng-app="demo">
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div data-ng-controller="DemoController">
<ul>
<li data-ng-repeat="item in items">
{{item}}
<button data-ng-click="removeItem($index)">Remove</button>
</li>
</ul>
<input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
</div>
</body>
</html>
JavaScript
"use strict";
var demo = angular.module("demo", []);
function DemoController($scope){
$scope.items = [
"potatoes",
"tomatoes",
"flour",
"sugar",
"salt"
];
$scope.addItem = function(item){
$scope.items.push(item);
$scope.newItem = null;
}
$scope.removeItem = function(index){
$scope.items.splice(index, 1);
}
}
For anyone returning to this question. The correct "Angular Way" to remove items from an array is with $filter. Just inject $filter into your controller and do the following:
$scope.items = $filter('filter')($scope.items, {name: '!ted'})
You don't need to load any additional libraries or resort to Javascript primitives.
You can use plain javascript - Array.prototype.filter()
$scope.items = $scope.items.filter(function(item) {
return item.name !== 'ted';
});
Because when you do shift() on an array, it changes the length of the array. So the for loop will be messed up. You can loop through from end to front to avoid this problem.
Btw, I assume you try to remove the element at the position i rather than the first element of the array. ($scope.items.shift(); in your code will remove the first element of the array)
for(var i = $scope.items.length - 1; i >= 0; i--){
if($scope.items[i].name == 'ted'){
$scope.items.splice(i,1);
}
}
Here is filter with Underscore library might help you, we remove item with name "ted"
$scope.items = _.filter($scope.items, function(item) {
return !(item.name == 'ted');
});
I liked the solution provided by #madhead
However the problem I had is that it wouldn't work for a sorted list so instead of passing the index to the delete function I passed the item and then got the index via indexof
e.g.:
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
An updated version of madheads example is below:
link to example
HTML
<!DOCTYPE html>
<html data-ng-app="demo">
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div data-ng-controller="DemoController">
<ul>
<li data-ng-repeat="item in items|orderBy:'toString()'">
{{item}}
<button data-ng-click="removeItem(item)">Remove</button>
</li>
</ul>
<input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
</div>
</body>
</html>
JavaScript
"use strict";
var demo = angular.module("demo", []);
function DemoController($scope){
$scope.items = [
"potatoes",
"tomatoes",
"flour",
"sugar",
"salt"
];
$scope.addItem = function(item){
$scope.items.push(item);
$scope.newItem = null;
}
$scope.removeItem = function(item){
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
}
}
Just a slight expansion on the 'angular' solution. I wanted to exclude an item based on it's numeric id, so the ! approach doesn't work.
The more general solution which should work for { name: 'ted' } or { id: 42 } is:
mycollection = $filter('filter')(myCollection, { id: theId }, function (obj, test) {
return obj !== test; });
My solution to this (which hasn't caused any performance issues):
Extend the array object with a method remove (i'm sure you will need it more than just one time):
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
I'm using it in all of my projects and credits go to John Resig John Resig's Site
Using forEach and a basic check:
$scope.items.forEach(function(element, index, array){
if(element.name === 'ted'){
$scope.items.remove(index);
}
});
At the end the $digest will be fired in angularjs and my UI is updated immediately without any recognizable lag.
If you have any function associated to list ,when you make the splice function, the association is deleted too. My solution:
$scope.remove = function() {
var oldList = $scope.items;
$scope.items = [];
angular.forEach(oldList, function(x) {
if (! x.done) $scope.items.push( { [ DATA OF EACH ITEM USING oldList(x) ] });
});
};
The list param is named items.
The param x.done indicate if the item will be deleted. Hope help you. Greetings.
Using the indexOf function was not cutting it on my collection of REST resources.
I had to create a function that retrieves the array index of a resource sitting in a collection of resources:
factory.getResourceIndex = function(resources, resource) {
var index = -1;
for (var i = 0; i < resources.length; i++) {
if (resources[i].id == resource.id) {
index = i;
}
}
return index;
}
$scope.unassignedTeams.splice(CommonService.getResourceIndex($scope.unassignedTeams, data), 1);
My solution was quite straight forward
app.controller('TaskController', function($scope) {
$scope.items = tasks;
$scope.addTask = function(task) {
task.created = Date.now();
$scope.items.push(task);
console.log($scope.items);
};
$scope.removeItem = function(item) {
// item is the index value which is obtained using $index in ng-repeat
$scope.items.splice(item, 1);
}
});
My items have unique id's. I am deleting one by filtering the model with angulars $filter service:
var myModel = [{id:12345, ...},{},{},...,{}];
...
// working within the item
function doSthWithItem(item){
...
myModel = $filter('filter')(myModel, function(value, index)
{return value.id !== item.id;}
);
}
As id you could also use the $$hashKey property of your model items: $$hashKey:"object:91"

Resources