Switching between modes / Accessing parts of data structure - angularjs

Given the following data:
{
id: "",
title: "",
// modes
one: {
stage: 1,
order: 3,
more: "",
}
two: {
stage: 14,
order: 5,
more: "",
}
// ...
},
// ...
how can I combine the following two pieces of code into one that uses a variable as a switching mechanism for the mode?
// If selected mode was "one"
<li ng-repeat="item in items | orderBy: ['one.stage', 'one.order']
| filter: oneFilter" ng-class="{ topline: isNewOneStage( item )}">
{{ item.title }},
{{ item.one.stage }}
// ...
</li>
// If selected mode was "two"
<li ng-repeat="item in items | orderBy: ['two.stage', 'two.order']
| filter: twoFilter" ng-class="{ topline: isNewTwoStage( item )}">
{{ item.title }},
{{ item.two.stage }}
// ...
</li>
Since the two pieces of code are completely identical - apart from the mode - I would like to avoid code duplication. (Note also that there will eventually be more than just two modes.)

I agree with Michael that you should probably reorganize your code, but if you must have it all at once you can do this depending on what version of angular you are using:
// variable mode is either 'one' or 'two'
<li ng-repeat="item in items | orderBy: [ mode + '.stage', mode + '.order']
| filter: (mode == 'one' ? oneFilter: twoFilter)" ng-class="{ topline: (mode == 'one' ? isNewOneStage: isNewTwoStage)( item )}">
{{ item.title }},
{{ item[mode].stage }}
// ...
</li>

Related

AngularJS custom filter in ng-repeat condition

I'm struggling to grasp how to make a custom filter. I'm looking for the function to filter by ItemID from a dropdown. This works fine, but I need it to stop filtering if the type is of value 8. This is because I'm changing the dataset where item_typeID does not exist
My current code
<ul ng-repeat="(key, item) in stock | filter: {item_code: searchCode} | filter: {item_name: searchName} | filter: {productID: product} | filter: {companyID: company} | filter: { item_typeID: type } ">
<li ng-show="stock_items" >
<div>Product</div>
{[{ item.product_name }]}
</li>
<li ng-show="stock_items" >
<div>Item Name</div>
<a ng-click="openModal(item.itemID)" class="activate_modal" name="modal_window">{[{ item.item_name }]}</a>
</li>
<li ng-show="stock_items">
<div>Item Code</div>
{[{ item.item_code }]}
</li>
<li ng-show="stock_items" >
<div>Stock level</div>
{[{ item.total_stock }]}
</li>
<li ng-show="stock_items">
<button ng-click="addItem(item.itemID, key)" ng-disabled="disable_them[key]" style="width:100%;" class="btn-icon add-to-cart">Add</button>
</li>
Just to let you know I've change the standard {{ tags to {[{ so that I can use the Blade templating in Laravel
I changed the filter line to contain this
<ul ng-repeat="(key, item) in stock | filter: {item_code: searchCode} | filter: {item_name: searchName} | filter: {productID: product} | filter: {companyID: company} | filter: typeFilter ">
This includes the new filter "typeFilter" Then in the Javascript added the following scope function
$scope.typeFilter = function (type) {
if($scope.type == undefined || $scope.type == "") {
return true;
} else if(type.item_typeID == $scope.type){
return true;
} else if($scope.type == 8) {
return true;
} else {
return false;
}
}

Compare two lists in angularJs

I have two list that creat from two different json object:
<ul ng-repeat="a in user.data">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
and :
<ul ng-repeat="x in job.data">
<li>
<md-checkbox>
{{ x.user.name }}
</md-checkbox>
</li>
</ul>
I have to compare two lists and remove {{ a.name }} that the same as {{ job.user.name }} . Comparing json objects that have different structure is hard. How can I compare this two list and remove repeated items?
You can use the filter filter ;) using a function instead of a string in the expression argument. Remember this is the syntax of filter
{{ filter_expression | filter : expression : comparator}}
The expression can be a string, an object or a function. Something like this will do
$scope.filterUnemployed = function(value) {
var jobs = $scope.job.data;
for (var i = 0; i < jobs.length; i++) {
// Search every object in the job.data array for a match.
// If found return false to remove this object from the results
if (jobs[i].user.name === value.name) {
return false;
}
}
// Otherwise return true to include it
return true;
}
And then apply the filter to your ng-repeat directive like this
<ul ng-repeat="a in user.data | filter:filterUnemployed">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
Note that this will not modify your original collection but will result in a new copy beign displayed in your html since this is usually the desired effect.
Check the sample for a working demo
angular.module('app', [])
.controller('SampleCtrl', function($scope) {
$scope.user = {
data: [{
name: 'John'
}, {
name: 'Mary'
}, {
name: 'Peter'
}, {
name: 'Jack'
}, {
name: 'Richard'
}, {
name: 'Elizabeth'
}]
};
$scope.job = {
data: [{
jobTitle: 'CEO',
user: {
name: 'John'
}
}, {
jobTitle: 'CFO',
user: {
name: 'Mary'
}
}, {
jobTitle: 'Analist',
user: {
name: 'Jack'
}
}]
};
$scope.filterUnemployed = function(value) {
var jobs = $scope.job.data;
for (var i = 0; i < jobs.length; i++) {
if (jobs[i].user.name === value.name) {
return false;
}
}
return true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="SampleCtrl">
<h1>All Users</h1>
<ul ng-repeat="a in user.data">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
<h1>Unemployed users</h1>
<ul ng-repeat="a in user.data | filter:filterUnemployed">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
<h1>Employed</h1>
<ul ng-repeat="x in job.data">
<li>
<md-checkbox>
{{ x.user.name }}
</md-checkbox>
</li>
</ul>
</div>
You can create a new array made from filtering one of your arrays :
var newArray = job.data.filter(function(jobData) {
return user.data.some(function(userData) {
return userData.name === jobData.user.name;
});
});
Something like this should help :
for(i=0; i<user.data.length;i++){
for(j=0; j<job.data.length;j++){
if(user.data[i].name === job.data[j].name){
user.date.splice(i,1);
}
}
}
I would appreciate some feedback, at least to know that my code helped you
You can use vanilla javascript, jQuery or library undescore.
Please check related links:
How can I merge two complex JSON objects with only unique or different values only showing in resultant array
How to merge two object values by keys
How to merge two arrays of JSON objects - removing duplicates and preserving order in Javascript/jQuery?
Merging two json objects in Java script?

How to iterate over inner object's properties in an AngularJS template?

I'm in the process of learning AngularJS. I would like to print out a list of objects and iterate over one of the object's inner object's properties. This looked like a standard procedure of using nested loops, however, it doesn't appear to be so simple.
My Controller is setup below. Essentially, it is a list of random vehicles.
var vehicleApp = angular.module("vehicleApp", []);
vehicleApp.controller('VehicleController', function ($scope) {
$scope.vehicles = [{
id: 0,
name: "car",
parts: {
wheels: 4,
doors: 4
}
}, {
id: 1,
name: "plane",
parts: {
wings: 2,
doors: 2
}
}, {
id: 2,
name: "boat",
parts: {
doors: 1
}
}];
});
I'd like to output the vehicles as such:
car
- wheels (4)
- doors (2)
plane
- wings (2)
- doors (2)
boat
- doors (1)
My template that I used was setup as such:
<div ng-app="vehicleApp" ng-controller="VehicleController">
<p ng-repeat="vehicle in vehicles">
{{ vehicle.name }}
</p>
<ul>
<li ng-repeat="(attribute, value) in vehicle.parts">
{{attribute}} ({{value}})
</li>
</ul>
</div>
This produces a list of the vehicles, but not the sub lists of the parts inner object.
Interestingly, enough, when I use {{ vehicle.parts }} it returns a JSON string of the parts inner object. Does AngularJS treat it as a string and hence, it is unable to print out the properties of the parts object?
You didn't enclose the second ngRepeat in the first one:
<div ng-app="vehicleApp" ng-controller="VehicleController">
<p ng-repeat="vehicle in vehicles">
{{ vehicle.name }}
<ul>
<li ng-repeat="(attribute, value) in vehicle.parts">
{{attribute}} ({{value}})
</li>
</ul>
</p>
</div>

AngularJS ngrepeat - filter based on scope data

I am trying to create a dropdown menu using angular ng-repeat.
I have a jd object with a field called parent_id which indicates parent node under which this node should show up. Help I need is to create filter based on previous filtered data as shown in the markup
My markup code:
<div >
<ul class="nav nav-pills" data-ng-controller= "MenuController" >
<li data-ng-class="{'active':getClass('/customers')}"
data-ng-repeat="menuItem in menuItems | filter: { ParentId: '0' }" >
{{ menuItem.Name }}
**<ul>
<li data-ng-repeat="menuItem1 in menuItems | filter: { ParentId: {{ menuItem1.ParentId }} }">
{{ menuItem1.Name }}
</li>
</ul>**
</li>
</ul>
</div>
My Service:
app.service('menuService', function () {
this.getMenuItems = function () {
return menuItems;
};
var menuItems = [
{
id: 'ABCDFER1', Name: 'Apperal', ParentId: 0, description: 'Beautifull Apparels'
},
{
id: 'ABCDFER2', Name: 'Electronics', ParentId: 0, description: 'Electronic bargains'
},
{
id: 'ABCDFER3', Name: 'Home & Kitchen', ParentId: 0, description: 'For your kitchen'
},
{
id: 'ABCDFER4', Name: 'Services', ParentId: 0, description: 'Services for you'
},
{
id: 'ABCDFER5', Name: 'Men', ParentId: 'ABCDFER1', description: 'Men Apperal'
},
{
id: 'ABCDFER6', Name: 'Women', ParentId: 'ABCDFER1', description: 'Women Apperal'
}
];
My controller:
$scope.menuItems = menuService.getMenuItems();
If I correctly understand what you're trying to accomplish, I believe you want this:
<div >
<ul class="nav nav-pills" data-ng-controller= "MenuController" >
<li data-ng-class="{'active':getClass('/customers')}"
data-ng-repeat="menuItem in menuItems | filter: { ParentId: '0' }" >
{{ menuItem.Name }}
<ul>
<li data-ng-repeat="menuItem1 in menuItems | filter: { ParentId: menuItem.id }">
{{ menuItem1.Name }}
</li>
</ul>
</li>
</ul>
</div>
Changes of note:
You want to filter on the id of the parent item, not the parentId of
the current item.
You don't need {{ }} around the filter value, because this is interpreted as code, not a template.

ng-repeat :filter by single field

I have an array of products that I'm repeating over using ng-repeat and am using
<div ng-repeat="product in products | filter:by_colour">
to filter these products by colour. The filter is working but if the product name / description etc contains the colour then the product remains after the filter is applied.
How do I set the filter to only apply to the colour field of my array rather than every field?
Specify the property (i.e. colour) where you want the filter to be applied:
<div ng-repeat="product in products | filter:{ colour: by_colour }">
See the example on the filter page. Use an object, and set the color in the color property:
Search by color: <input type="text" ng-model="search.color">
<div ng-repeat="product in products | filter:search">
You can filter by an object with a property matching the objects you have to filter on it:
app.controller('FooCtrl', function($scope) {
$scope.products = [
{ id: 1, name: 'test', color: 'red' },
{ id: 2, name: 'bob', color: 'blue' }
/*... etc... */
];
});
<div ng-repeat="product in products | filter: { color: 'red' }">
This can of course be passed in by variable, as Mark Rajcok suggested.
If you want to filter on a grandchild (or deeper) of the given object, you can continue to build out your object hierarchy. For example, if you want to filter on 'thing.properties.title', you can do the following:
<div ng-repeat="thing in things | filter: { properties: { title: title_filter } }">
You can also filter on multiple properties of an object just by adding them to your filter object:
<div ng-repeat="thing in things | filter: { properties: { title: title_filter, id: id_filter } }">
Best way to do this is to use a function:
html
<div ng-repeat="product in products | filter: myFilter">
javascript
$scope.myFilter = function (item) {
return item === 'red' || item === 'blue';
};
Alternatively, you can use ngHide or ngShow to dynamically show and hide elements based on a certain criteria.
Be careful with angular filter. If you want select specific value in field, you can't use filter.
Example:
javascript
app.controller('FooCtrl', function($scope) {
$scope.products = [
{ id: 1, name: 'test', color: 'lightblue' },
{ id: 2, name: 'bob', color: 'blue' }
/*... etc... */
];
});
html
<div ng-repeat="product in products | filter: { color: 'blue' }">
This will select both, because use something like substr That means you want select product where "color" contains string "blue" and not where "color" is "blue".
Search by color:
<input type="text" ng-model="searchinput">
<div ng-repeat="product in products | filter:{color:searchinput}">
you can do an inner nest too.
filter:{prop1:{innerprop1:searchinput}}
If you were to do the following:
<li class="active-item" ng-repeat="item in mc.pageData.items | filter: { itemTypeId: 2, itemStatus: 1 } | orderBy : 'listIndex'"
id="{{item.id}}">
<span class="item-title">{{preference.itemTitle}}</span>
</li>
...you would not only get items of itemTypeId 2 and itemStatus 1, but you would also get items with itemType 20, 22, 202, 123 and itemStatus 10, 11, 101, 123. This is because the filter: {...} syntax works like a string contains query.
However, if you were to add the : true condition, it would do filter by exact match:
<li class="active-item" ng-repeat="item in mc.pageData.items | filter: { itemTypeId: 2, itemStatus: 1 } : true | orderBy : 'listIndex'"
id="{{item.id}}">
<span class="item-title">{{preference.itemTitle}}</span>
</li>
my way is this
subjcts is
[{"id":"1","title":"GFATM"},{"id":"2","title":"Court Case"},{"id":"3","title":"Renewal\/Validity"},{"id":"4","title":"Change of Details"},{"id":"5","title":"Student Query"},{"id":"6","title":"Complains"}]
sub is a Input field or whatever you like
Displaying like this
<div ng-if="x.id === sub" ng-repeat=" x in subjcts">{{x.title}}</div>
You must use
filter:{color_name:by_colour} instead of
filter:by_colour
If you want to match with a single property of an object, then write that property instead of object, otherwise some other property will get match.
Specify the property in filter, of object on which you want to apply filter:
//Suppose Object
var users = [{
"firstname": "XYZ",
"lastname": "ABC",
"Address": "HOUSE NO-1, Example Street, Example Town"
},
{
"firstname": "QWE",
"lastname": "YUIKJH",
"Address": "HOUSE NO-11, Example Street1, Example Town1"
}]
But you want to apply filter only on firstname
<input type = "text" ng-model = "first_name_model"/>
<div ng-repeat="user in users| filter:{ firstname: first_name_model}">
If you want filter for one field:
label>Any: <input ng-model="search.color"></label> <br>
<tr ng-repeat="friendObj in friends | filter:search:strict">
If you want filter for all field:
label>Any: <input ng-model="search.$"></label> <br>
<tr ng-repeat="friendObj in friends | filter:search:strict">
and
https://docs.angularjs.org/api/ng/filter/filter good for you

Resources