I am trying to filter my results on multiple checkboxes.
Here is my JSFIDDLE
How do i write dynamic ng-model for the checkboxes for the filter to take reflect?
function MainCtrl($scope) {
$scope.languages = [
{ name: 'persian', _id : 0 },
{ name: 'English', _id : 1 },
{ name: 'spanish', _id : 2 }
];
$scope.bu = [
{ name: 'A', _id : 1 },
{ name: 'B', _id : 2 },
{ name: 'C', _id : 3 },
{ name: 'D', _id : 4 },
{ name: 'E', _id : 5 }
];
$scope.array = [
{
"id": 910,
"language": {
"_id": "333",
"name": "Persian",
"abbreviation": "PE"
},
"business_unit": {
"_id": "2",
"name": "B"
}
},
{
"id": 909,
"language": {
"_id": "456",
"name": "English",
"abbreviation": "EN"
},
"business_unit": {
"_id": "3",
"name": "C"
}
},
{
"id": 908,
"language": {
"_id": "456",
"name": "Spanish",
"abbreviation": "SP"
},
"business_unit": {
"_id": "4",
"name": "D"
}
},
{
"id": 911,
"language": {
"_id": "343",
"name": "German",
"abbreviation": "GE"
},
"business_unit": {
"_id": "5",
"name": "E"
}
},
{
"id": 912,
"language": {
"_id": "696",
"name": "Russian",
"abbreviation": "RU"
},
"business_unit": {
"_id": "1",
"name": "A"
}
}]
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="MainCtrl">
<li ng-repeat="o in languages" ng-model="lang.language.name">
<input type="checkbox">
{{o.name}},
`</li>
<br><br><br>
<li ng-repeat="o in bu">
<input type="checkbox" ng-model="bu.business_unit.name">
{{o.name}},
`</li>
<br><br><br>
<div ng-repeat="arr in array filter : lang | filter : bu">
{{arr.language.name}} "and" {{arr.business_unit.name}}
</div>
<div>
You can use custom filter to achieve your goal:
custom fileter:
filter('myFilter', function() {
return function(items, search) {
var filterItems = {
search: search,
result: []
};
if (!search.needFilter) {
return items;
}
angular.forEach(items, function(value, key) {
if (this.search.language[value.language.name] === true || this.search.business_unit[value.business_unit.name] === true) {
this.result.push(value);
}
}, filterItems);
return filterItems.result;
};
})
HTML:
<p>Search by Language:</p>
<li ng-repeat="o in languages">
<input type="checkbox" ng-model="search.language[o.name]"> {{o.name}}
</li>
<p>Search by Unit:</p>
<li ng-repeat="o in bu">
<input type="checkbox" ng-model="search.business_unit[o.name]"> {{o.name}}
</li>
<p><b>Result:</b></p>
<div ng-repeat="arr in array | myFilter : search:false ">
{{arr.language.name}} "and" {{arr.business_unit.name}}
</div>
For more details see PLUNKER DEMO
Related
I'm working with BootstrapVue. I have following problem - I have a select dropdown in my parent.vue where I select my ID (as you can see it's my props) and I want to compare this with my json file...
Now I need to do following:
Check my selected ID (from parent.vue) with my json file and find the correct ID
Put all Articel in my dropdown selection
emit Rank of selected Articel back to parent
I don't have any clue how to solve that with a nested JSON File.. I think I have to use a v-for loop..
Thanks in advance for helping me out!
my code:
<template>
<b-card>
<div class="mt-2">CLOTHING ITEM</div>
<b-form-select type="text"></b-form-select>
</b-card>
</template>
<script>
import json from './json/ID.json'
export default {
name: "customerChoice",
data() {
return {
json: json,
}
},
props: ["ID"]
}
</script>
my nested json:
[
{
"ID": "1111",
"Product": {
"1": {
"Articel": "Jeans",
"Rank": "1"
},
"2": {
"Articel": "T-Shirt",
"Rank": "2"
}
}
},
{
"ID": "2222",
"Product": {
"1": {
"Articel": "Hoodie",
"Rank": "2"
},
"2": {
"Articel": "Jeans",
"Rank": ""
}
}
},
{
"ID": "3333",
"Product": {
"1": {
"Articel": "Socks",
"Rank": "1"
}
}
}
]
If I understand you correctly, take a look at following snippet:
Vue.component('Child', {
template: `
<b-card>
<div class="mt-2">CLOTHING ITEM</div>
<b-form-select type="text"
v-model="selected"
:options="articles"
text-field="Articel"
value-field="Rank"
>
</b-form-select>
</b-card>
`,
data() {
return {
json: [
{ID: "1111", "Product": {"1": {"Rank": "1", "Articel": "Jeans"}, "2": {"Articel": "T-Shirt", "Rank": "2"}}},
{ID: "2222", "Product": {"1": {"Articel": "Hoodie","Rank": "2"}, "2": {"Articel": "Jeans", "Rank": ""}}},
{ID: "3333", "Product": {"1": {"Articel": "Socks", "Rank": "1"}}}
],
selected: null,
}
},
props: ["id"],
computed: {
articles() {
const res = []
const art = this.json.find(j => j.ID === this.id)
for(let key in art.Product) {
res.push(art.Product[key])
}
return res
}
},
watch: {
selected() {
this.$emit('changed', this.selected)
}
}
})
new Vue({
el: '#demo',
data() {
return {
parentId: '1111',
rank: ''
}
},
methods: {
rankReceived(val) {
console.log(val)
this.rank = val
}
}
})
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<div id="demo">
<h3>{{rank}}</h3>
<Child :id="parentId" #changed="rankReceived" />
</div>
I have a list of items which I am looping through with *ngFor. I have category buttons above the list like in the HTML shown below. What I need to implement is when clicking on the button, I want to filter the list based on the category of the button clicked.
I am not sure what approach is better, whether to go for a pipe or just a function
<div class="quick-filter-container">
<button class="quick-filter-button active" [class.active]="isActive('cat1')" (click)="setActive('cat1')"
type="button">Category1</button>
<button class="quick-filter-button" [class.active]="isActive('cat2')" (click)="setActive('cat2')"
type="button">Category2</button>
<button class="quick-filter-button" [class.active]="isActive('cat3')" (click)="setActive('cat3')"
type="button">Category3</button>
<button class="quick-filter-button" [class.active]="isActive('cat4')" (click)="setActive('cat4')"
type="button">Category4</button>
</div>
<div class="meter-reading-list-conatiner" *ngFor="let data of filteredList">
<h1>{{data.address.addressName}}</h1>
<div *ngFor="let header of data.premiseMeters">
<span> ID: {{header.meterNumber}}</span>
</div>
</div>
setActive(buttonName) {
this.activeButton = buttonName;
}
isActive(buttonName) {
return this.activeButton === buttonName;
}
JSON
this.filteredList = {
"meterReadPanelReportList": [
{
"premiseId": 674052,
"address": {
"addressName": "CHILDRENS ROAD, LIMERICK, CO. LIMERICK"
},
"premiseMeters": [
{
"meterNumber": "Y00001410",
"utilType": "elec",
"category": "category1",
"meters": [
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
},
{
"lastReadingDate": "24/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
}
]
},
{
"meterNumber": "Z00001410",
"utilType": "gas",
"category": "category3",
"meters": [
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
},
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
}
]
}
]
},
{
"premiseId": 674052,
"address": {
"addressName": "CHILDRENS ROAD, LIMERICK, CO. LIMERICK"
},
"premiseMeters": [
{
"meterNumber": "Y00001410",
"utilType": "gas",
"category": "category2",
"meters": [
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
},
{
"lastReadingDate": "24/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
}
]
},
{
"meterNumber": "Z00001410",
"utilType": "gas",
"category": "category3",
"meters": [
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
},
{
"lastReadingDate": "23/09/2020",
"lastReadingMethod": "E",
"lastReadingStatus": "Pending"
}
]
}
]
}
]
}
Call the function from html and pass the category name as an argument
<button class="quick-filter-button active" [class.active]="isActive('cat1')" (click)="myClickFunction('category1')"
type="button">Category1</button>
Filter the data in components on a common function. Expecting the unfiltered dataset named as data here.
myClickFunction(category){
this.filteredList = data.filter(item => item.category === category );
}
I want to display the name and photoUrl in the HTML template of an Angular 6 app, how do I access the name and photoUrl elements only in the below array:
{
"key":"key0",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":3243242,
"name":"Ryan",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/male-29.jpg",
"rating":5
}
]
}
{
"key":"key1",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":6757587,
"name":"Sarah",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-70.jpg",
"rating":16
}
]
}
You can use *ngFor directive provided by Angular
.component.html
<div *ngFor="let user of users">
<div *ngFor="let value of values;i = index">
<div>{{value.name}}</div>
<div>{{value.photoUrl}}</div>
</div>
<div>
.component.ts
users = [
{
"key":"key0",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":3243242,
"name":"Ryan",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/male-29.jpg",
"rating":5
}
]
}.
{
"key":"key1",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":6757587,
"name":"Sarah",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-70.jpg",
"rating":16
}
]
}
]
Your JSON is not valid, however i made few adjustments
[ {
"key": "key0",
"value": [
{
"id": 567657,
"name": "Jess",
"photoUrl": "https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating": 30
},
{
"id": 3243242,
"name": "Ryan",
"photoUrl": "https://d3iw72m71ie81c.cloudfront.net/male-29.jpg",
"rating": 5
}
] }, {
"key": "key1",
"value": [
{
"id": 567657,
"name": "Jess",
"photoUrl": "https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating": 30
},
{
"id": 6757587,
"name": "Sarah",
"photoUrl": "https://d3iw72m71ie81c.cloudfront.net/female-70.jpg",
"rating": 16
}
] } ]
and you just need nested ngFor as follows,
<ul>
<li *ngFor="let group of myArray">
{{group.name}}
<ul>
<li *ngFor="let light of group.value">
<h1>Photo </h1> {{light.photoUrl}}
<h1>Name </h1> {{light.name}}
</li>
</ul>
</li>
</ul>
STACKBLITZ DEMO
component.ts
user_Array = [
{
"key":"key0",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":3243242,
"name":"Ryan",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/male-29.jpg",
"rating":5
}
]
}.
{
"key":"key1",
"value":[
{
"id":567657,
"name":"Jess",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-50.jpeg",
"rating":30
},
{
"id":6757587,
"name":"Sarah",
"photoUrl":"https://d3iw72m71ie81c.cloudfront.net/female-70.jpg",
"rating":16
}
]
}
]
component.html
<div *ngFor="let user of user_Array">
<span>{{user?.name}}</span>
<img src="{{user?.photoUrl}}">
<div>
comment
by adding '?' html file will not generate error if that specific variable is not present.
it is always safe to add "?" while accessing ts variable
I want to generate dynamic data field using value of prop passed in child component.
Code:
...
<datafieldcheckbox :categories="abc" #call-method="callfilteredproducts"></datafieldcheckbox>
new Vue({
el: "#app",
data: {
abc: null, // this will generate based on a value of prop passed in child component.
products: [
{
"id": "1",
"name": "Product1",
"abc": "EEE",
"skill": "Easy",
"color": "blue",
"price": 100.00
},
{
"id": 2,
"name": "Product2",
"abc": "EEE",
"skill": "Intermediate",
"color": "red",
"price": 120.00
},
{
"id": 3,
"name": "Product3",
"abc": "Office",
"skill": "Intermediate",
"color": "green",
"price": 190.00
}
]
...
const dfCheckBox = Vue.component('datafieldcheckbox', {
template: `<div id="one">
<h4><strong>Categories</strong></h4>
<ul class="categoriesFilter">
<li v-for="category in categories"><label><input type="checkbox" :id="category" :value="category" v-model="selectedFilters.categories" #click="filterProducts()"><span class="categoryName">{{category}}</span></label></li>
</ul>
</div>`,
data() {
return{
products : null,
selectedFilters: {
categories: [],
colors: [],
minPrice: null,
maxPrice: null
}
}
},
props : ['categories'],
methods: {
filterProducts(){
this.$emit('call-method', this.selectedFilters);
}
}
});
like in above code If I write abc then it will generate this kinda code in parent data:
Now let's say I have data in products and I want to find unique values of a key that is passed from child props.
Just pass the product array to child component and filter the category by checkbox. pls try this
template
<!-- child -->
<script type="text/x-template" id="grid-template">
<div>
<h2>
category list:
</h2>
<ul>
<li v-for="category in categories">
<label>{{category.abc}}</label>
<input type="checkbox" :value="category" v-model="selectedCategory" #change="emitback(selectedCategory)"/>
</li>
</ul>
</div>
</script>
<!-- parent -->
<div id="demo">
<h2>
selected category:
</h2>
<ul>
<li v-for="category in selectedCategory">
{{category.abc}}
</li>
</ul>
<datafieldcheckbox :categories="product" #call="callfilteredproducts"></datafieldcheckbox>
</div>
script
Vue.component('datafieldcheckbox', {
template: '#grid-template',
props: {
categories: Array,
},
created(){
console.log(this.categories);
},
data: function () {
return {
selectedCategory:[]
}
},
methods: {
emitback(selectedVal){
this.$emit('call',selectedVal);
}
}
})
// bootstrap the demo
var demo = new Vue({
el: '#demo',
data: {
selectedCategory:[],
product:[
{
"id": "1",
"name": "Product1",
"abc": "EEE",
"skill": "Easy",
"color": "blue",
"price": 100.00
},
{
"id": 2,
"name": "Product2",
"abc": "EEE",
"skill": "Intermediate",
"color": "red",
"price": 120.00
},
{
"id": 3,
"name": "Product3",
"abc": "Office",
"skill": "Intermediate",
"color": "green",
"price": 190.00
}
]
},
methods:{
callfilteredproducts(event){
console.log(event);
this.selectedCategory = event
}
}
})
demo Jsfiddle
I using Angular 1.5.5, and angular-material 1.1.0 here.
When I adding md-chips in ng-repeat loop it do not working, I got follow error:
angular.js:13550 TypeError: this.items.some is not a function
at e.appendChip (http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js:13:28477)....
md-template do not what that should (as return i go value from md-item-text, which is _id, but i need $chip.text);
it don't addind an item even if i changing md-item-text="item.text" (which is wrong but for test).
It do working well for a single item (with out ng-repeat).
<md-list-item ng-repeat="i in dialogueItems track by $index">
<md-chips ng-model="i.text" md-removable="true" md-enable-chip-edit="true" md-autocomplete-snap="true" md-require-match="true">
<md-autocomplete md-min-length="0" md-match-case-insensitive="true" md-selected-item="i.selectedItem" md-search-text="i.searchText" md-items="item in loadItems(i.searchText, i.tagId)" md-item-text="i.selectedItem._id" md-autoselect="true" md-no-cache="true"
placeholder="Words">
<span md-highlight-text="i.searchText">{{item.text}}</span>
</md-autocomplete>
<md-chip-template>
{{$chip.text}}
</md-chip-template>
</md-chips>
</md-list-item>
JS
$scope.dialogueItems = [{
tagId: 1,
text: [],
searchText: null,
selectedItem: null
}];
$scope.loadItems = function(query, tagId) {
return $http({
method: 'POST',
url: '/api/wordsapi/searchwords',
data: {
text: query,
tagId: tagId,
count: 10
}
}).then(function(d) {
return d.data.words;
});
};
And example of api result:
{
"words": [{
"text": "you",
"_id": "030423b3-99ed-42a2-bab7-7efd10a68cfa"
}, {
"text": "i",
"_id": "a833abe2-c602-4cd7-b765-5b14229ecc7d"
}, {
"text": "god",
"_id": "724766b6-c83c-4679-bf28-827ad1a516eb"
}, {
"text": "a",
"_id": "c2b7920b-7541-42f1-9b61-84a1d7c42930"
}, {
"text": "bless",
"_id": "6ea9b56f-b47b-4453-b97c-0b5ba4311992"
}, {
"text": "am",
"_id": "ab12f90d-9b40-4e33-af13-14e75fbb405a"
}, {
"text": "your",
"_id": "55910a38-4435-4db4-8498-6cddaf4b0059"
}, {
"text": "with",
"_id": "7c5a2627-777f-443e-9f58-83c62e4fae11"
}, {
"text": "are",
"_id": "befa650c-e894-477b-9e67-2f7fb24e40b5"
}, {
"text": "good",
"_id": "90ee8243-630f-4f91-9ecf-0a6469716e0d"
}],
"allCount": 1024
}