angular js filter inside ng-change - angularjs

my data template looks like this,
scope.items=[{"name:"John","score":1},{"name":"Rick","score":5},{"name":"Peter","score":2}]
I have a select box with values 0,1,2,3,4,5 and would like to filter items object based on score value selected in dropdown
scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"condition 2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
HTML
<select id="scoreS" ng-model="score" ng-change="updateScore()">
<option
ng-repeat="score in scores"
value="{{score.value}}">{{score.name}}</option>
</select>
So when i select condition 0 from my dropdown box I need to filter items to show only those objects matching score(key) 0 and when I select 1 from the drop down , match only items having score(key) 1 and so on. how do you do this inside updateScore() function ?

Try like this. it's better use ng-options instead of ng-repeat in drop-down
var app = angular.module('anApp', []);
app.controller('aCtrl', function($scope) {
$scope.items=[
{"name":"John","score":1}
,{"name":"Rick","score":5}
,{"name":"Peter","score":2}
]
$scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="anApp" ng-controller="aCtrl as vm">
<select id="scoreS" ng-model="score" ng-options="score.value as score.name for score in scores ">
</select>
<div ng-repeat="item in items| filter:{score:score}">
<span>{{item.name}}</span>
</div>
</div>

use filter option to filter the data according to drop down
<div ng-repeat="item in items | filter :score">
Demo
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.scores= [
{
"name":"condition 0",
"value":"0"
},
{
"name":"condition 1",
"value":"1"
},
{
"name":"condition 2",
"value":"2"
},
{
"name":"condition 3",
"value":"3"
},
{
"name":"condition 4",
"value":"4"
},
{
"name":"condition 5",
"value":"5"
}
]
$scope.items=[{"name":"John","score":1},{"name":"Rick","score":5},{"name":"Peter","score":2}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select id="scoreS" ng-model="score" ng-change="updateScore()">
<option ng-repeat="score in scores" value="{{score.value}}">{{score.name}}</option>
</select>
<div ng-repeat="item in items | filter :score">
{{item.name}}= {{item.score}}
</div>
</div>

Related

md-select with recursive options

I am trying to iterate through an array of categories with subcategories.
The problem. I have this array of categories:
$scope.categories = [{
"_id": 1,
"name": "Cat 1",
"categories": {
"_id": 11,
"name": "Cat 11",
"categories": {
"_id": 111,
"name": "Cat 111",
"categories": null
}
}
}, {
"_id": 2,
"name": "Cat 2",
"categories": null
}, {
"_id": 3,
"name": "Cat 3",
"categories": null
}];
As you can see, is an array of objects with subcategories, so I know that I need a recursive solution.
I need to show all the categories into a md-select (it is not necesary group it, but it will be great) and I am trying this:
<md-input-container class="md-block">
<label>Categories</label>
<md-select ng-model="selectedCategory">
<md-option ng-value="category._id" ng-repeat-start="category in categories">{{category.name}}</md-option>
<span ng-repeat-end ng-include="'subcategories'" ng-if="category.categories"></span>
</md-select>
</md-input-container>
<script type="text/ng-template" id="subcategories">
{{category.name}}
<md-option ng-value="category._id" ng-repeat-start="category in category.categories">{{category.name}}</md-option>
<span ng-repeat-end ng-include="'subcategories'" ng-if="category.categories"></span>
It works partially, but it is not the result expected.
What I want? Something like this
What I have? This code
Tell me if need more details.
Thanks
You can simply flatten your list and style elements by their nesting level.
angular
.module('app', ['ngMaterial'])
.controller('AppController', function($scope) {
$scope.categories = [{
"_id": 1,
"name": "Cat 1",
"categories": [{
"_id": 11,
"name": "Cat 11",
"categories": [{
"_id": 111,
"name": "Cat 111",
"categories": null
}]
}]
}, {
"_id": 2,
"name": "Cat 2",
"categories": null
}, {
"_id": 3,
"name": "Cat 3",
"categories": null
}];
$scope.flattenCategories = flatten($scope.categories, 0);
function flatten(categories, level) {
var flat = [];
for (var i = 0, n = categories.length, category; category = categories[i]; i++) {
flat.push({
_id: category._id,
name: category.name,
level: level
});
if (category.categories) {
flat = flat.concat(flatten(category.categories, level + 1));
}
}
return flat;
}
});
.subcategory-0 .md-text {
margin-left: 0;
}
.subcategory-1 .md-text {
margin-left: 8px;
}
.subcategory-2 .md-text {
margin-left: 16px;
}
.subcategory-3 .md-text {
margin-left: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-messages.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.4/angular-material.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
<div ng-app="app" ng-controller="AppController">
<form name="myForm">
<md-input-container class="md-block">
<label>Categories</label>
<md-select ng-model="selectedCategory" name="myCategory">
<md-option ng-class="'subcategory-' + category.level" ng-value="category._id" ng-repeat="category in flattenCategories track by category._id">{{ category.name }}</md-option>
</md-select>
<!-- <pre ng-bind="flattenCategories | json"></pre> -->
</md-input-container>
</form>
</div>

AngularJS displays only elements that meet a certain condition

in my ng-repeat list I am displaying object elements from an object array $scope.toBuy:
$scope.toBuy=[
cookies={
name:'cookies',quantity:0,bought:false
},
water={
name:'water',quantity:0,bought:false
},
bananas={
name:'bananas',quantity:0,bought:false
},
milk={
name:'milk',quantity:0,bought:false
},
coconut={
name:'coconut',quantity:0,bought:false
}
];
and I initialize all element's bought field to false. How do I display in a ng-repeat list that only shows elements that have false value in their bought field? I tried this:
<ul>
<li ng-repeat="item in toBuy | filter:{item.bought===false }">Buy 10 {{item.quantity}} {{item.name}} <button class="btn btn-default" ng-click="btnOnClick(item.name)"> Bought</button></li>
</ul>
but none of the elements displayed when the page is loaded. If I removed the filter, the whole list displays, which means I applied the filter wrong.
You are using invalid javascript object syntax {item.bought===false }
Change to
ng-repeat="item in toBuy | filter:{bought:false }"
DEMO
Your JSON is not a valid JSON.
Try this valid JSON :
[{
"name": "cookies",
"quantity": 0,
"bought": true
}, {
"name": "water",
"quantity": 0,
"bought": true
}, {
"name": "bananas",
"quantity": 0,
"bought": true
}, {
"name": "milk",
"quantity": 0,
"bought": false
}, {
"name": "coconut",
"quantity": 0,
"bought": false
}]
Working demo :
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.toBuy=[{
"name": "cookies",
"quantity": 0,
"bought": true
}, {
"name": "water",
"quantity": 0,
"bought": true
}, {
"name": "bananas",
"quantity": 0,
"bought": true
}, {
"name": "milk",
"quantity": 0,
"bought": false
}, {
"name": "coconut",
"quantity": 0,
"bought": false
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in toBuy | filter : {bought:false}">Buy 10 {{item.quantity}} {{item.name}} <button class="btn btn-default" ng-click="btnOnClick(item.name)"> Bought</button></li>
</ul>
</div>
Use ng-if (or ng-show):
<div ng-repeat="item in toBuy">
<div ng-if="item.bought===false">
Buy 10 {{item.quantity}} {{item.name}}
</div>
</div>
Try this:
<li ng-repeat="item in toBuy | filter:item.bought==false">
Or
<li ng-repeat="item in toBuy | filter:{bought:false}">
Will work, the second is a better way to achieve this.

Track by index doesnt reset after changing selection

i have a cascading select option, and is working well, the problem is that when i change the first selected option, in the second selection option (subcategory), it keeps the index. So case i change the category (first select), in the second selection it goes to the option position that it was.
For better understanding, please check this example i made and try changin the options. You will notice that in the second selec option keeps the position index that had in the previous category selected. It doesnt starts to 0 when changing the category.
Link: http://jsfiddle.net/Fqfg3/28/
Js:
var app = angular.module('app', []);
app.controller('PeopleCtrl', function ($http,$scope) {
vm = this;
vm.options = [
{
"_id": "1",
"label": "Category 1",
"childs": [
"Category 1 -> Subcategory 1",
"Category 1 -> Subcategory 2",
"others"
]
},
{
"_id": "2",
"label": "Category 2",
"childs": [
"Category 2 -> Subcategory 1",
"Category 2 -> Subcategory 2",
"others"
]
},
{
"_id": "3",
"label": "Category 3",
"childs": [
"Category 3 -> Subcategory 1",
"Category 3 -> Subcategory 2",
"others"
]
}];
});
html:
<div ng-app="app" ng-controller="PeopleCtrl as ctrl" class="container">
{{ctrl.options}}
<div class="form-group question-wrapper">
<select class="form-control"
name="category"
ng-options="option.label for option in ctrl.options track by option._id"
ng-model="ctrl.supportMail.selected">
</select>
</div>
<div class="form-group question-wrapper">
<select id="sub" class="form-control"
name="subcategory"
>
<option ng-repeat="child in ctrl.supportMail.selected.childs track by $index">{{child}}</option>
</select>
</div>
</div>
You can use ng-change in main select to reset the subselect to default.
Here's is a demonstration working:
(function() {
"use strict";
angular.module('app', [])
.controller('mainCtrl', function() {
var vm = this;
vm.options = [
{
"_id":"1",
"label":"Category 1",
"childs":[
"Category 1 -> Subcategory 1",
"Category 1 -> Subcategory 2",
"others"
]
},
{
"_id":"2",
"label":"Category 2",
"childs":[
"Category 2 -> Subcategory 1",
"Category 2 -> Subcategory 2",
"others"
]
},
{
"_id":"3",
"label":"Category 3",
"childs":[
"Category 3 -> Subcategory 1",
"Category 3 -> Subcategory 2",
"others"
]
}
];
vm.reset_subSelect = function() {
vm.supportMail.child = vm.supportMail.selected.childs[0];
}
});
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl as ctrl">
<div class="container">
<div class="form-group question-wrapper">
<select class="form-control" name="category" ng-options="option.label for option in ctrl.options track by option._id" ng-model="ctrl.supportMail.selected" ng-change="ctrl.reset_subSelect()" ng-init="ctrl.supportMail.selected = ctrl.options[0]">
</select>
</div>
<div class="form-group question-wrapper">
<select class="form-control" id="sub" name="subcategory" ng-options="child for child in ctrl.supportMail.selected.childs" ng-model="ctrl.supportMail.child" ng-init="ctrl.supportMail.child = ctrl.supportMail.selected.childs[0]">
</select>
</div>
</div>
</body>
</html>
I hope it helps.
By adding an ng-model to your subcategory I was able to resolve the issue you can see the example here
Hope this helps.

Angular ngclick add class to all siblings

How to add class to all siblings expect the clicked one. When I click the one I want, I want to apply class blue to all siblings not the one I clicked.
http://jsfiddle.net/bm6kujL1/
<div ng-app="editer" ng-controller="myCtrl" class="container">
<div ng-repeat="item in items">
<div class="wrap" ng-click="show =!show" ng-class="{'blue':show}">
<span>{{item.name}}</span>
<span ng-show="show">{{item.thing}}</span>
</div>
</div>
</div>
//JS
function myCtrl($scope) {
$scope.editedItem = null;
$scope.items = [{
name: "item #1",
thing: "thing 1"
}, {
name: "item #2",
thing: "thing 2"
}, {
name: "item #3",
thing: "thing 3"
}];
$scope.show = false;
}
var editer = angular.module('editer', []);
//CSS
.wrap {
background: yellow;
}
.blue {
background: blue;
}
I made some small changes to your JS fiddle, and it works now. Basically, you only had one attribute called show for all items, but you needed to know for each one if it should be blue or not.
JS:
function myCtrl($scope){
$scope.editedItem = null;
$scope.items = [
{ name :"item #1", thing: "thing 1", selected: false},
{ name :"item #2", thing: "thing 2", selected: false},
{ name :"item #3", thing: "thing 3", selected: false}
];
function resetAllItems() {
for (i in $scope.items) {
$scope.items[i].selected = false;
}
}
$scope.selectItem = function(item) {
resetAllItems();
item.selected = true;
}
}
HTML
<div ng-app="editer" ng-controller="myCtrl" class="container">
<div ng-repeat="item in items">
<div class="wrap" ng-click="selectItem(item)" ng-class="{'blue': item.selected}">
<span>{{item.name}}</span>
<span ng-show="item.selected" >{{item.thing}}</span>
</div>
</div>
</div>
You can use a function instead and use the item show property.
HTML:
<div class="wrap" ng-click="toggleShow(item)" ng-class="{'blue':item.show}">
<span>{{item.name}}</span>
<span ng-show="item.show">{{item.thing}}</span>
</div>
JS:
$scope.items = [{
name: "item #1",
thing: "thing 1",
show: false
}, {
name: "item #2",
thing: "thing 2",
show: false
}, {
name: "item #3",
thing: "thing 3",
show: false
}];
$scope.toggleShow = function(item){
for(var i=0; i<$scope.items.length; ++i){
if($scope.items[i] === item){
$scope.items[i].show = false;
continue;
}
$scope.items[i].show = true;
}
}
fiddle:
http://jsfiddle.net/bm6kujL1/2/

In Angular how can you dynamically add an input to be applied once

I have searched the web and found no example. I wonder if someone could help.
I have two instances of a dropdown or maybe more and I want to apply the add input dynamically to only that form but it applies to everyone with that ng-model everywhere on the web page.
The code is here https://plnkr.co/edit/PPDYKjztPF528yli9FbN
HTML:
<div class="main-content__right" ng-controller="QuestionController">
<div ng-repeat="element in questionList">
<fieldset>
<div ng-repeat="choice in formOptionData track by $index">
<a class="remove-field remove u-pull-right" ng-click="remove()">Remove</a>
<input id="input{{choice.name}}" placeholder="{{choice.label}}" type="number" name="{{choice.name}}">
</div>
<div id="add-more" class="well">
<div class="field">
<div style="width:100%;" class="dropdown">
<select name="{{options.name}}" id="select" data-ng-model="selectedValue" data-ng-options="options as options.label for options in element.inputElement | orderBy:'label'" ng-change="onCategoryChange(selectedValue)">
<option value="" data-id="null" disabled="" selected="">Select an item...</option>
</select>
</div>
</div>
{{formData}}
</div>
</fieldset>
</div>
</div>
APP.js
var app = angular.module("cab", []);
app.controller('QuestionController', function($scope) {
$scope.formOptionData = [];
$scope.selectedValue = {};
$scope.questionList = [{
"sectionTitle": "Travel",
"inputType": "select",
"inputElement": [{
"label": "Public transport",
"name": "travelOutgoing",
"helpInfo": "include train journeys",
"type": "select"
}, {
"label": "Taxis",
"name": "travelOutgoing",
"type": "select"
}
]
},
{
"sectionTitle": "Leisure",
"title": "Enter the amount you spend on entertainment and leisure. Leave them blank if they don\"t apply to you.",
"inputType": "select",
"inputElement": [
{
"label": "Eating out",
"name": "leisureOutgoing",
"helpInfo": "Include coffees, teas and snacks",
"type": "select"
},
{
"label": "Going out",
"name": "leisureOutgoing",
"helpInfo": "Include drinks, taxis, admission charges",
"type": "select"
}
] }
];
$scope.onCategoryChange = function(selectedItem) {
this.formOptionData.push(selectedItem);
};
$scope.remove = function(element) {
this.formData.splice(element,1);
};
});

Resources