Filtering json response in Vue - javascript

I am having trouble with filtering a json response in Vue.
return this.offers.filter(type => type.offers == 'Junior');
Whenever I leave it as return this.offers, in my html this is being displayed:
{"-MN5agCddYAdy7c8GSSz": { "companyName": "dawdwad", "image": "da", "jobDescription": "dada", "location": "daw", "salary": "dadaw", "skill": "dawda", "tags": "dada", "title": "dwa" }, "-MN7vsTsNohgQigd3S26": { "companyName": "ejadfjaq", "image": "", "jobDescription": "dada", "location": "2sjawdja", "salary": "40324032", "skill": "Junior", "tags": "ux", "title": "fawd" } }
But I want only the fields with "skill": "Junior" to appear.

Your JSON is an object but filter only works on arrays. You can use the for...in loop in a computed to reformat it and filter it the way you like:
computed: {
filteredOffers() {
const filteredOffers = [];
for(const key in this.offers) {
if (this.offers[key].skill == 'Junior') filteredOffers.push(this.offers[key]);
}
return filteredOffers;
}
}
This returns an array of the objects you want. If you just want to display them raw in your template:
<div id="app">
{{ filteredOffers }}
</div>
Here's a demo:
new Vue({
el: "#app",
data() {
return {
offers: {
"-MN5agCddYAdy7c8GSSz": {
"companyName":"dawdwad",
"image":"da",
"jobDescription":"dada",
"location":"daw",
"salary":"dadaw",
"skill":"dawda",
"tags":"dada",
"title":"dwa"
},
"-MN7vsTsNohgQigd3S26":{
"companyName":"ejadfjaq",
"image":"",
"jobDescription":"dada",
"location":"2sjawdja",
"salary":"40324032",
"skill":"Junior",
"tags":"ux",
"title":"fawd"
}
}
}
},
computed: {
filteredOffers() {
const filteredOffers = [];
for(const key in this.offers) {
if (this.offers[key].skill == 'Junior') filteredOffers.push(this.offers[key]);
}
return filteredOffers;
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
{{ filteredOffers }}
</div>

Related

Vue.js 3 and search

I have a data coming from API. It is an array of "houses".
Code looks like this:
<template>
<div class="search__sort">
<input v-model="search" placeholder="Search for a house">
<button class="sort__button">Price</button>
<button class="sort__button">Size</button>
</div>
<div v-for="house in houses" :key="house.id" class="house">
<router-link :to="{ name: 'HouseDetails', params: { id: house.id}}" >
<h2>ID = {{ house }}</h2>
<h3> {{ house.location.street}} </h3>
<img :src="house.image" />
</router-link>
<button v-if="house.madeByMe" class="delete" #click="deleteHouse(house.id)">Delete</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Houses',
data(){
return {
houses: [],
}
},
created() {
this.getHouses();
},
methods: {
getHouses(){
// GET request using axios with set headers
const headers = { "CENSORED": "CENSORED" };
axios.get('myAPI', { headers })
.then(response => this.houses = response.data);
},
deleteHouse(id) {
const headers = { "CENSORED": "CENSORED" };
axios.delete('myAPI' + id, { headers })
.then(response => {
console.log(response);
})
.catch(function (error) {
console.log(error.response);
});
},
},
}
</script>
I somehow need to implement the filter by text input, so that for example, if user types a city name it will show all of those houses or a street name to filter that by street.
Any suggestions how I can do that with code that I already have?
You can use computed property:
new Vue({
el: '#demo',
data() {
return {
search: '',
houses: [{ "id": 2, "image": "myAPI/house1.jpg", "price": 123, "rooms": { "bedrooms": 1, "bathrooms": 1 }, "size": 500, "description": "oui", "location": { "street": "street 20", "city": "assas", "zip": "asasdd" }, "createdAt": "2020-05-07", "constructionYear": 2000, "hasGarage": false, "madeByMe": false }, { "id": 3, "image": "myAPI/house1.jpg", "price": 123, "rooms": { "bedrooms": 1, "bathrooms": 1 }, "size": 500, "description": "oui", "location": { "street": "street 20", "city": "adb", "zip": "asasdd" }, "createdAt": "2020-05-07", "constructionYear": 2000, "hasGarage": false, "madeByMe": false },{ "id": 4, "image": "myAPI/house1.jpg", "price": 123, "rooms": { "bedrooms": 1, "bathrooms": 1 }, "size": 500, "description": "oui", "location": { "street": "street 20", "city": "bbb", "zip": "asasdd" }, "createdAt": "2020-05-07", "constructionYear": 2000, "hasGarage": false, "madeByMe": false }],
}
},
computed: {
filteredHouses(){
return this.houses.filter(h => h.location.city.toLowerCase().includes(this.search.toLowerCase()))
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div class="search__sort">
<input v-model="search" placeholder="Search for a house">
<button class="sort__button">Price</button>
<button class="sort__button">Size</button>
</div>
<div v-for="house in filteredHouses" :key="house.id" class="house">
<h3> {{ house.location.city}} </h3>
<img :src="house.image" />
</div>
</div>
You will want to distinguish the difference between houses and displayedHouses such that, displayedHouses is your filtered array.
<h2>ID = {{ house }}</h2> is not going to play well with your testing
displayedHouses will be a computed looking something like:
computed:
{
/**
* #return {array} List of displayed houses from search input
*/
displayedHouses()
{
if (!this.houses || !this.houses.length)
{
return []
}
if (!this.search)
{
return this.houses
}
return this.houses.filter( (house) =>
{
return house.city.includes(this.search) || house.state.includes(this.search) // || whatever else you want
})
}
},

Compare values over components / BootstrapVue

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>

getting two values of an array of object displaying one versus the other on vue js

im working in a vue js exercise , being on that point where in i have an array of objects and i want to display 2 players with diferents names , as final result on whichever html display result,: here my array of objects:
[
{
"id": 1,
"player": {
"id": 1,
"player": "Jack Bauer",
"email": "j.bauer#ctu.gov2",
"password": "24"
}
},
{
"id": 2,
"player": {
"id": 2,
"player": "Chloe O'Brian",
"email": "c.obrian#ctu.gov",
"password": "42"
}
}
]
and this is my template on vuejs in order to show lets say Chloe O'Brian versus Jack Bauer
<div v-for='(players,i) in getGamePlayerId' :key='players' >
the player is {{getGamePlayerId.game.players_in_game}}</div>
</div>
Is there a way using a double loop to compare both names and expose both different name
If I understood your question correctly, in my opinion the best way is to first work on the array a little.
Maybe grouping the players 2by2 and then loop that array instead. To do this you can use array.reduce.
new Vue({
el: '#app',
data: {
players: [
{
"id": 1,
"player": {
"id": 1,
"player": "Jack Bauer",
"email": "j.bauer#ctu.gov2",
"password": "24"
}
},
{
"id": 2,
"player": {
"id": 2,
"player": "Chloe O'Brian",
"email": "c.obrian#ctu.gov",
"password": "42"
}
}
]
},
computed: {
matches () {
return this.players.reduce((matches, item, index, arr) => {
if (index !== arr.length - 1) {
matches.push({player: item, opponent: arr[index + 1]})
}
return matches
}, []);
}
}
})
<div id="app">
<h3>Matches</h3>
<div v-for="(match, index) in matches" :key="index">
<div>
{{ match.player.player.player }} <strong>vs</strong> {{ match.opponent.player.player }} </div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

How to display values in post { } in following example in vuejs?

{"status":true,"data":[{"agent_id":7042,"p_id":7039,"post":{"author":83,"created_on":"2017-10-07 14:28:36","sub_category":"Litigation Support","category":"Personal Investigation","budget":"5555","views":"0","status":"986","id":7039,"country":"India","state":"Kerala","quote":{"ref_id":"61","agent_id":7042,"p_id":7039,"created_on":"2017-10-09 10:41:15"}}},{"agent_id":7042,"p_id":7040,"post":{"author":83,"created_on":"2017-10-09 12:06:01","sub_category":"Pre-Matrimonial Investigation","category":"Personal Investigation","budget":"5555","views":"0","status":"984","id":7040,"country":"India","state":"Kerala","quote":{"ref_id":"61","agent_id":7042,"p_id":7039,"created_on":"2017-10-09 10:41:15"}}}]}
<div id="quotes">
<div v-for="post in data" class="mke_">
<card-component v-bind:id="post.p_id" v-bind:ins="post.category" v-bind:country="post.country" v-bind:state="post.state" v-bind:attachment_id="post.attachment_preview">
</card-component>
</div>
this is my vue js code to get the values, The values obtained is in the above format
quotes = new Vue({
'el' : '#quotes',
data : {
posts : [],
has_no_posts : true
},
mounted : function(){
var self = this;
$.ajax({
url : "url",
method : "POST",
dataType : "JSON",
data : {},
success : function(e){
if(e.status == true){
self.data = e.data;
if(e.data.length > 0)
self.has_no_posts = false;
}
}
});
}
});
This is my code to display the same which is getting error. So somebody please help me to didplay the same
You have to be more careful with your data.
First issue: you assign the result of your ajax query to self.data instead of self.posts.
Second issue: every "post" actually contains another "post" object with the actual post properties. So you need to use post.post.category to grab that.
See the below snippet. Note: I replaced your aja call with a setTimeout(0).
Finally, you should turn has_no_posts into a computed property that depends on self.posts.
var e = {
"status": true,
"data": [{
"agent_id": 7042,
"p_id": 7039,
"post": {
"author": 83,
"created_on": "2017-10-07 14:28:36",
"sub_category": "Litigation Support",
"category": "Personal Investigation",
"budget": "5555",
"views": "0",
"status": "986",
"id": 7039,
"country": "India",
"state": "Kerala",
"quote": {
"ref_id": "61",
"agent_id": 7042,
"p_id": 7039,
"created_on": "2017-10-09 10:41:15"
}
}
}, {
"agent_id": 7042,
"p_id": 7040,
"post": {
"author": 83,
"created_on": "2017-10-09 12:06:01",
"sub_category": "Pre-Matrimonial Investigation",
"category": "Personal Investigation",
"budget": "5555",
"views": "0",
"status": "984",
"id": 7040,
"country": "India",
"state": "Kerala",
"quote": {
"ref_id": "61",
"agent_id": 7042,
"p_id": 7039,
"created_on": "2017-10-09 10:41:15"
}
}
}]
};
new Vue({
el: '#quotes',
data: {
posts: [],
has_no_posts: true
},
mounted: function() {
var self = this;
setTimeout(function() {
self.posts = e.data;
self.has_no_posts = e.data.length > 0;
}, 0);
}
});
<script src="https://unpkg.com/vue"></script>
<div id="quotes">
<div v-for="post in posts" class="mke_">
<span v-bind:id="post.p_id">{{post.post.category}} - {{post.post.country}} - {{post.post.state}}</span>
</div>
</div>

How to change json structure to look like another json structure

I want to change my json structure, how can I do it?
im getting a json that looks like this:
body: {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
but I need it in this structure:
body: {
bulks: [{
"id": "111111",
"name": "exp1",
"status": 100000
}, {
"id": "222222",
"name": "exp2",
"status": 200000
}, {
"id": "333333",
"name": "exp3",
"status": 300000
}]
}
Cause in my html I want to read it like this:
<div *ngIf="showingList">
<div class="list-bg" *ngFor="#bulk of listBulks | async">
ID: {{bulk.id}} name of item: {{bulk.name}}
</div>
</div>
Using Object#entries and Array#map with spread operator.
const data={body:{111111:{name:"exp1",status:1e4},222222:{name:"exp2",status:2e4},333333:{name:"exp3",status:3e4}}};
const res = {body:{bulk:Object
.entries(data.body)
.map(a=>({id: a[0], ...a[1]}))}};
console.log(res);
You can do it using reduce:
var body = {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
var bodyArray = Object.keys(body).reduce(function(result, key) {
var item = body[key];
item.id = key;
result.push(item)
return result;
}, []);
As a simplest alternative to reduce, you could use the map() function.
const body = {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
const newArray = Object.keys(body).map(function(key) {
const newObject = {
id: key,
...body[key]
};
return newObject;
});
console.log(newArray);

Categories