Il jump right to the case.
Basicly when you have an array of objects like this:
{id: 1, name: "Hello", location: "New york", streetNumber: 50}
Then you have an input field:
<input type="text" ng-model="search.$" />
And the following table:
<table>
<thead>
<th>Name</th>
<th>Location</th>
<th>Street number</th>
</thead>
<tr ng-repeat="item in items | filter:search">
<td>
{{item.name}}
</td>
<td>
{{item.location}}
</td>
<td>
{{item.streetNumber}}
</td>
</tr>
</table>
So when you type into the search field: "1".
Then you will also get the object where the id matches 1.
My question is how can i exclude items that are not shown?
Fiddle
Well, take a look at the docs
A special property name ($ by default) can be used (e.g. as in {$:
"text"}) to accept a match against any property of the object or its
nested object properties.
That's why the results with ids satisfying the criterion get included.
Solution 1, simple but slower working
Add another filtering
<tr ng-repeat="item in items | filter : search | filter : { id: '!search.$' }">
Solution 2, difficult but quick
Consider writing your own filter, e.g.
JS
app.filter('searchFields', function () {
return function (array, fields, string) {
fields = fields.split(',');
var i,
fieldsLength = fields.length;
return array.filter(function (item) {
for (i = 0; i < fieldsLength; i++) {
if (typeof item[fields[i]] === 'undefined') {
continue;
}
return (item[fields[i]] + '').indexOf(string) !== -1;
}
});
};
});
HTML
<tr ng-repeat="item in items | searchFields : 'name,location,streetNumber' : search.$">
Related
AngularJS code
This is my code in AngularJS that I want to correct. Currently in the last rows of the table I print out the name and marks of the student with the highest marks. I want the name and score to change if a user edits the preprogrammed marks.
Example: The 2nd highest person becomes the highest if the highest is changed to 0
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope)
{
{
var x=[];
for (var i = 0; i<20; i++)
{
var R = Math.round((Math.random() * 10) * 10);
x[i]=R;
}
};
$scope.names = [
{name:'Priya',age:'19',gender:'Female',English:x[0], Hindi:x[1]},
....
{name:'Jiah', age:'18', gender:'Female',English:x[18],Hindi:x[19]}
];
$scope.sortColumn ="name";
$scope.avg = function(e, h){
if(!h) h=0;
if(!e) e=0;
return ( parseInt(h)+parseInt(e))/2;
}
$scope.delete = function (name)
{
$scope.names.splice( $scope.names.indexOf(name), 1 );
}
});
</script>
HTML Code
This is the code where I want the changes to occur. At the bottom of the HTML code you can see where I want the highest marks for Hindi and English.
<table>
<tr ng-repeat ="x in names | orderBy:sortColumn">
<td>{{x.name}}</td>
<td>{{x.age}}</td>
<td>{{x.gender}}</td>
<td><input type="text" ng-model="x.English"></td>
<td><input type="text" ng-model="x.Hindi"></td>
<td>
<button>Delete</button>
</td>
</tr>
</table>
<table ng-model="total">
<tr><td>The total is: {{total}}</td></tr>
Below is where I want the highest marks in English then Hindi to appear.
<tr><td ng-repeat="x in names |orderBy:'-English' | limitTo:1"> {{x.name}} has the highest marks in English: {{x.English}}</td></tr>
<tr><td ng-repeat="x in names |orderBy:'-Hindi' | limitTo:1"> {{x.name}} has the highest marks in Hindi: {{x.Hindi}}</td></tr>
</table>
Rather than using ngRepeat, you can create another function which will return the student with the highest value in a certain subject:
$scope.highestStudent = function(key) {
return $scope.names.reduce(function(prev, curr) {
return prev[key] > curr[key] ? prev : curr;
});
}
Using Reduce we are reducing the Array into a single result: which of these Students, has the highest value in a certain subject.
With this, we can use this instead to display the result:
<tr><td> {{highestStudent('English').name}} has the highest marks in English: {{highestStudent('English').English}}</td></tr>
<tr><td> {{highestStudent('Hindi').name}} has the highest marks in Hindi: {{highestStudent('Hindi').Hindi}}</td></tr>
I think the problem is that when you update the inputs, the model is set to "string" instead of "number".
You should change the type from "text" to "number".
<td><input type="number" ng-model="x.English"></td>
<td><input type="number" ng-model="x.Hindi"></td>
Also to properly ordering empty values:
<tr><td ng-repeat="x in names | orderBy:['!-English', '-English'] | limitTo:1"> {{x.name}} has the highest marks in English: {{x.English}}</td></tr>
<tr><td ng-repeat="x in names | orderBy:['!-Hindi', '-Hindi'] | limitTo:1"> {{x.name}} has the highest marks in Hindi: {{x.Hindi}}</td></tr>
Working jsfiddle:
http://jsfiddle.net/fk5zjuq8/
Iam completely confused at a point and need anyone's help here. Went through various examples but nothing could help.
I have a created dynamic table, added with checkboxes. Now whenever a row is selected its id will be bound to an array and it will be diplayed at the top of table.
What I need is:The code for functionality of select all check box. And whenever all the rows are selected by select all checkbox, its ids has to be displayed.
Below is the code for the table:
<table>
<thead>
<tr>
<th>
<input name="all"
type="checkbox"
ng-click="selectAll()" />
</th>
<th>ID</th>
<th>Date</th>
</tr>
</thead>
<tbody ng-repeat="x in cons">
<tr>
<td>
<input type="checkbox"
name="selectedids[]"
value="{{x.id}}"
ng-checked="idSelection.indexOf(x.id) > -1"
ng-click="toggleSelection(x.id, idSelection)"> </td>
<td>{{x.id}}</td>
<td>{{x.title}}</td>
</tr>
</tbody>
app.js:
$scope.idSelection = [];
$scope.toggleSelection = function toggleSelection(selectionName, listSelection) {
var idx = listSelection.indexOf(selectionName);
// is currently selected
if (idx > -1) {
listSelection.splice(idx, 1);
}
// is newly selected
else {
listSelection.push(selectionName);
}
};
//$scope.selectAll=function(){}
//Need code for this function to work
Here is a demo: http://plnkr.co/edit/m9eQeXRMwzRdfCUi5YpX?p=preview.
Will be grateful, if anyone can guide.
You need a variable to keep track of whether 'All' is currently active or not. If not, we create a new array of all item id's using the array map function, and pass this to idSelection. If allSelected is currently active, we pass an empty array to idSelection
$scope.allSelected = false;
$scope.selectAll = function() {
$scope.allSelected = !$scope.allSelected;
if($scope.allSelected) {
$scope.idSelection = $scope.cons.map(function(item) {
return item.id;
});
} else {
$scope.idSelection = [];
}
}
I want to sum the product count which are added dynamically using JSON array.
<tr ng-repeat="(key,val) in form.products">
<td>{{ProductName(key)}}</td>
<td >
<input type="text" name="products" ng-model="form.products[key]" class="form-control">
</td>
</tr>
How can I get the sum of products in the above example?
use lodash
presuming the value you want to sum is in a property called 'price':
{{_(form.products).mapValues('price').sum()}}
you may need to get lodash into your scope first. In the controller, something like:
scope._ = _;
or this approach
you are using an 'object with properties' instead of 'an array of objects', that is why you cant use your example above , $scope.products.length;....
Your product object with its properties :
$scope.products ={
"1":"20",//property 1 with value 20
"2":"35",//property 2 with value 35
"3":"150"//property 3 with value 150
}
The data Object (object with properties as you have it):
$scope.myData = {"1":120,"2":250,"3":500};
Function that iterates into object's properties and sum the price:
//read object properties and sum price
$scope.calculateSum = function(data){
var sum=0;
var counter=0;
for (var property in data) {
if (data.hasOwnProperty(property)) {
sum += data[property];
counter++;
}
}
return sum;
};
Function that iterates into object properties and count the products
//read object properties and count the products
$scope.countProducts = function(data){
var counter=0;
for (var property in data) {
if (data.hasOwnProperty(property)) {
counter++;
}
}
return counter;
};
Into your HTML template:
<table>
<tr ng-repeat="(key,value) in myData track by $index">
<td>
<input type="text" name="id" ng-model="key" class="form-control">
</td>
<td>
<input type="text" name="price" ng-model="value" class="form-control">
</td>
</tr>
<tr>
<td>Products: {{countProducts(myData)}}</td>
<td>Sum: {{calculateSum(myData)}}</td>
</tr>
</table>
I have done a live example that counts the products and also sum the products price: http://plnkr.co/edit/FmJhvV?p=preview
Hope helps, good luck.
I want to add a row in the table on click of "Add" button.I am trying to accomplish this using "ng-show" directive but that row is displaying even without clicking "Add" button. Please help me with this. Here is the code -
home.html -
<table class="table">
<thead>
<tr>
<th>SNo.</th>
<th>UserId</th>
<th>Name</th>
<th>Share</th>
<th>Paid</th>
</tr>
</thead>
<tbody ng-repeat="member in members">
<tr>
<td>{{member.sNo}}</td>
<td>{{member.id}}</td>
<td>{{member.name}}</td>
<td>{{member.share}}</td>
<td>{{member.paid}}</td>
</tr>
<tr ng-show="show" class="ng-hide"> //the row which is to be added
<td><span>{{counter}}</span></td>
<td><input type="text" required ng-model="new.id"></td>
<td><input type="text" required ng-model="new.name"></td>
<td><input type="text" required ng-model="new.share"></td>
<td><input type="text" required ng-model="new.paid"></td>
</tr>
</tbody>
</table>
<div><input type="button" value="Add" ng-click="addMember()"/></div>
controller.js -
expmodule.controller('expenseForm', function($scope, sharedProperties) {
var id, expenses = {};
$scope.show = false;
$scope.members = [{
sNo: "1",
id: "abc#gmail.com",
name: "Neha",
share: 200,
paid: 400,
}, {
sNo: "2",
id: "xyz#gmail.com",
name: "Sneha",
share: 200,
paid: 400,
}];
$scope.counter = $scope.members.length++;
$scope.addMember = function () {
$scope.show = true;
return $scope.newRow = true;
}
});
Are you looking for something like this? http://plnkr.co/edit/jxXX5sWhgmYrANV7ieKM?p=preview
There are few things which are not correct in the code provided in the question.
The add row is inside ng-repeat. So a new add row will be added for each member.
Also as the show variable is inside ng-repeat it will be a child of parent scope and will be always false as per the current logic.
$scope.counter = $scope.members.length++ This will increase the array length by 1 and the new object in the array will be undefined. I guess you wanted to display the counter in the new add row. It can be simple done like this - {{members.length + 1}} in the add row rather than creating a new scope variable for this. Also this will always have the latest value when ever a new member is added.
The return statement in the addMember function has a assignment operation.
It seems to work fine (see demo below).
Of course, you should place the ng-repeat="member in members" to the <tr> not <tbody> (unless you want to have multiple tbodies).
And you should change $scope.counter = $scope.members.length++; to $scope.counter = $scope.members.length + 1;
See, also, this short demo.
My application allows you to track orders in a store database. This database contains a weak entity used for notes which is attached to an orderID. I want to allow users to be able to apply to same 'note' to many orders at the same time, but there are some fields in the notes table that are dependent on the location of the sale. In other words, you should only be allowed to apply the same note if all the sale locations are the same.
Simplified View:
#using (Html.BeginForm("Create", "Note", FormMethod.Get, new { name = "editForm" }))
{
<table id="DataTable">
<tr>
<th>
<input type="button" value="Edit" onclick="checkboxValidation()"/>
</th>
<th>
#Html.DisplayNameFor(model => model.OrderID)
</th>
<th>
#Html.DisplayNameFor(model => model.location)
</th>
</tr>
#foreach (var item in Model)
{
<tr >
<td>
<input type="checkbox" name="ids" value="#item.orderID" />
</td>
<td>
#Html.ActionLink(item.OrderID.ToString(), "Details", "Search", new { orderID = item.orderID.ToString() }, null)
</td>
<td>
#Html.DisplayFor(modelItem => item.location)
</td>
</tr>
}
</table>
checkboxValidation() is a javascript function I wrote to check if at least 1 checkbox is checked. How would I add a check to make sure all of the locations on checked lines are the same? Is this even possible? Thanks
EDIT: I missed a detail. When clicking the edit button, if the check is successful, it submits the form, which brings up the notes editor.
Should be fairly straightforward using JQuery:
// find all the checked rows
var checkedItems = $("#DataTable").find("tr td input[type=checkbox]");
// construct a locations array for all checked items
var locations = [];
checkedItems.each(function(index, element) {
if ($(element).is(":checked")) {
locations.push($(this).closest("td").next("td").next("td").text().trim());
}
});
// confirm each location is the same
var valid = true;
locations.each(function(index, element) {
if (index > 0 && locations[index-1] != element) {
valid = false;
return;
}
});
One additional thing you might want to do, is add some data tags to your tr and td elements, so that you can write more robust selectors that won't break with a minor UI re-arrangement (like tr[data-role=check] and tr[data-role=location], etc).
(Using JQuery closest and and JQuery each.)