Modify false values inside javascript object - javascript

Using the JSON file I am trying to build a product list.
There are cases where products don't have data (was price) and in this case I dont want to display anything.
If "was_price" is false I want to modify its property to an empty string ' ' but I cannot print it even if in console.log works.
{
"product_arr" : [
{
"name": "Example1",
"price": 40,
"was_price": false,
"reviews": 80,
"img": 1
}, {
"name": "Example2",
"price": 250,
"was_price": 300,
"reviews": 98,
"img": 2
}
]
}
fetch('./data/product.json')
.then(function (response) {
return response.json();
})
.then(function (data) {
appendData(data);
checkFalsePrice(data);
})
.catch(function (err) {
console.log(err);
});
function appendData(data) {
const html = data.product_arr.map(item =>
`<div class="product">
<div class="row">
<div class="col-sm-3 child">
<div class="row">
<div class="media"><img src="img/${item.img}.jpg" /></div>
</div>
<div class="row">
<div class="product-title">${item.name}</div>
</div>
<div class="row">
<div class="price"> £${item.price/100}</div>
</div>
<div class="row">
<div class="was-price"><span>Was</span> <span>${item.was_price/100}</span></div>
</div>
<div class="row">
<div class="reviews">${item.reviews}% Reviews Score</div>
</div>
</div>
</div>
</div>`)
document.getElementById("content").innerHTML = html.join("")
But return doesn't work
function checkFalsePrice(data) {
data.product_arr.map(function (arr) {
let wasPrice = arr.was_price;
if(wasPrice === false) {
return wasPrice.innerHTML = '';
} else {
return wasPrice;
}
})
}
<div id="content"></div>

dont use checkFalsePrice just try this
<div class="row">
<div class="was-price"><span>Was</span> <span>${item.was_price/100 || ''}</span</div>
</div>

Related

How to manipulate div class on rendered element using map() javascript

How do I use javascript to add class=open into rendered <div class="card flex-row"> using map().
On the inspect element browser i see the reaction on click but that action didn't adding the determined class
Here is my code :
function fetchingData() {
fetch("http://localhost:3001/quote/sendquote")
.then((response) => {
if (!response.ok) {
throw Error;
}
return response.json();
})
.then((data) => {
console.log(data);
const rend = data.person
.map((data) => {
return `
<div class='card flex-row'>
<img src='https://png.pngtree.com/png-vector/20191023/ourlarge/pngtree-user-vector-icon-with-white-background-png-image_1849343.jpg' class='book'>
<div class='flex-column info'>
<div class='title' id="person">Dear ${data.frstname}</div>
<div class='author'></div>
<div class='hidden bottom summary'>
<input id="quote" type="text" value="">
</div>
</div>
<div class='flex-column group'>
<div class='members'>
<span class='current'>14</span> /
<span class='max'>30</span>
</div>
<div class='hidden bottom'>
<button class='simple'>Submit</button>
</div>
</div>
</div>`;
})
.join("");
console.log(rend);
document.querySelector(".center").insertAdjacentHTML("afterbegin", rend);
})
.catch((err) => {
console.log("rejected", err);
});
}
fetchingData();
<div class='container'>
<div class='center list flex-column'>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script>
let old = $(".card").get(0);
$(".card").click(function() {
if (old != null && $(old).hasClass("open")) $(old).toggleClass("open");
$(this).toggleClass("open");
old = this;
});
</script>
<script>
</script>

Check length of Object size / BootstrapVue

I've updated my code - I think before it was not clear enough.
I try to write in my number and get my input in the other two fields but only when its correct otherwise my input fields should include informatione "false number", but it's not working..
also when I input 3 numbers and they are in my json file it gives console.log "Not in file" - but it is..
Hope now someone can help me out..
<template>
<div>
<div class='inputArea mt-2' v-for='(element, index) in inputs' :key='index'>
<b-button v-b-toggle="'newElement'+index" variant='secondary btn-block'>Element {{index+1}}</b-button>
<b-collapse :id="'newElement'+index">
<div class='m-2 mt-3'>
<table class='table table-striped mt-2'>
<tbody>
<tr>
<div class='row'>
<div class='col-md-6 m-1'>
<div class='mt-2'>Input Number</div>
<b-form-input v-model="element.Number" #input="searchelementInformations(element.Number)"></b-form-input>
</div>
</div>
<div class='row'>
<div class='col-md-5 ml-1 mr-1'>
<div class='mt-2'>Autofill 1</div>
<b-form-input :value="element.Autofill1" ></b-form-input>
</div>
<div class='col-md-5 ml-1 mr-1'>
<div class='mt-2'>Autofill 2</div>
<b-form-input :value="element.Autofill2"></b-form-input>
</div>
</div>
</tr>
</tbody>
</table>
</div>
</b-collapse>
</div>
<div class='mt-4 mb-5 ml-3 mr-3'>
<b-button #click='addelement' variant='block' type='button'>Add Element</b-button>
</div>
</div>
</template>
<script>
export default {
methods: {
addelement() {
this.inputs.push ({
});
},
searchelementInformations(inputNumber) {
var size = Object.keys(inputNumber).length;
console.log(size);
this.jsonAutofill.forEach(element => {
if ((size === 3) && (+element.Number === +inputNumber)) {
for(const key of Object.keys(element)) {
inputNumber = element[key];
console.log(key);
console.log(inputNumber);
}
}
else if (size !== 3) {
console.log("Not correct length");
}
else if ((size === 3) && (+element.Number !== +inputNumber)){
console.log("Not in file")
}
});
},
},
data() {
return {
inputs:[{}],
Artikelnummer: [],
jsonAutofill: [
{ "Number": 123, "Autofill1": "Test1", "Autofill2": "Hello"},
{ "Number": 321, "Autofill1": "Test2", "Autofill2": "Goodbye"},
],
}
}
};
</script>
<style scoped>
</style>
I would watch for the reactive data, like this:
<script>
export default {
data () {
return {
number: 0,
message: ""
}
},
watch: {
"number"(){
if (this.number.length == 5) {
this.message = "Do this"
}
else {
this.message = "Do that"
}
}
}
}
</script>
<template>
<input v-model="number">
<div>{{ message }}</div>
</template>
This is the answer.. I need to reference "Number" in my Object.keys than I will get the length.
var size = Object.keys(inputNumber.Number).length;
console.log(size);

How to sort array of object based on div position

I have a HTML list with rearrangable divs, they can be moved up and down, once rearranged I need to change the array with the same order of the HTML elements.
HTML:
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
Array:
"listArray": [
{
"id": 0,
"name": "apple",
},
{
"id": 1,
"name": "pear",
},
{
"id": 2,
"name": "orange",
},
]
How can I get this result using the id value as a reference?
"listArray": [
{
"id": 2,
"name": "orange",
},
{
"id": 1,
"name": "pear",
},
{
"id": 0,
"name": "apple",
},
]
I tried:
var unitsRows = document.querySelectorAll("#list .row");
var newList = [];
for (var row of unitsRows) {
var rowId = row.id
rowId = rowId.replace('listUnit', "");
var newEl = listArray[rowId];
newList.push(newEl);
}
listArray = newList;
The order of the objects changes but it's not the same of the HTML after some rearrangmet.
You can do this every time it changes.
I had to fix your invalid markup
const listArray = [...document.querySelectorAll("#List .row")]
.map(row => ({ id: +row.id.match(/\d+/g), name: row.querySelector('div').textContent.trim() }))
console.log(listArray)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
You can get the list on UI, then you sort the listArray based on it.
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
I updated your code and print the result in the console. You can check it:
var listArray = new Array({
"id": 0,
"name": "apple",
}, {
"id": 1,
"name": "pear",
}, {
"id": 2,
"name": "orange",
});
var unitsRows = document.querySelectorAll(".row p");
var names = [];
[].forEach.call(unitsRows, function(item) {
names.push(item.innerHTML.toLowerCase());
});
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
console.log('Result', listArray);
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
</div>
1- Your html code is wrong, modify the structure.
2- You have an element with id='List', not an element with class=list. And you need the children of that div, So modify your selector:
var unitsRows = document.querySelectorAll("#List .row");
3- Get text of p element with:
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
var unitsRows = document.querySelectorAll("#List .row");
let newList = [];
unitsRows.forEach(itm => {
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
newList.push({
id: itm.id.replace('listUnit', ""),
text
})
})
console.log(newList)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>

Vue use v-for to iterate over an nested array of API response

I'm starting to learn vue, I was trying to practice a little bit and i got stuck with the for-loops.
I'm making a call to an api I've developed to understand better the data handling. The output of the call is:
[
{
"_id": "ID1",
"customerID": "ASDF",
"purchases": [
{
"laptop": "DELL",
"price": "500"
},
{
"monitor": "DELL",
"price": "200"
}
]
},
{
"_id": "ID2",
"customerID": "FDSA",
"purchases": [
{
"laptop": "MacBook",
"price": "1800"
},
{
"monitor": "DELL",
"price": "300"
}
]
}
]
The purpose I have is to use v-for to go through the array of purchases, so that it can display the contents of the array for each entry in the json.
The vue template I'm using is:
<template>
<div>
<div class="card" v-for="data in purchases" :key="data.purchases">
<div class="card-image">
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">PURCHASES</p>
<div
class="columns is-variable is-1-mobile is-0-tablet is-3-desktop is-8-widescreen is-2-fullhd"
>
<div class="column">Laptop: {{data.purchases[0].laptop}}</div>
<div class="column">Monitor: {{data.purchases[0].monitor}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Script in the vue file:
<script>
import { ref } from "#vue/composition-api";
export default {
setup() {
const purchases = ref([]);
const API_url = "http://localhost:8383/purchases";
async function getData() {
const reponse = await fetch(API_url);
const json = await reponse.json();
purchases.value = json;
console.log(purchases);
}
getData();
return {
purchases,
};
},
};
</script>
I know I'm only showing the first element of the array and that's precisely my question, how can I go through the whole array with the v-for.
I would very much appreciate the help :)
Create another nested v-for to loop through data.purchases :
<template>
<div>
<div class="card" v-for="data in purchases" :key="data.purchases">
<div class="card-image">
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">PURCHASES</p>
<div
class="columns is-variable is-1-mobile is-0-tablet is-3-desktop is-8-widescreen is-2-fullhd"
>
<template v-for="purchase in data.purchases">
<div class="column">Laptop: {{purchase.laptop}}</div>
<div class="column">Monitor: {{purchase.monitor}}</div>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>

Infinite loop VueJS API calls

I got infinite api calls when this method setCurrentDateFilter called after clicking on radio button. It looks like my filtered list rerenders every time because of reactivity. But actually i don't understand the reason why. Everything was fine before i did this additional api call on button click.
index.html partially
<div class="row align-items-center justify-content-center">
<b-form-group>
<b-form-radio-group buttons v-model="selected_date" :change="setCurrentDateFilter()" name="date_filter">
<b-form-radio value="today" button-variant="outline-success">Сегодня</b-form-radio>
<b-form-radio value="tomorrow" button-variant="outline-success">Завтра</b-form-radio>
<!-- <b-form-radio value="specific" button-variant="outline-success" disabled>Выбрать дату</b-form-radio> -->
</b-form-radio-group>
</b-form-group>
</div>
<div class="container">
<div class="section-top-border" v-for="(event, i) in filteredEvents" :key="event.id">
<div class="row">
<div class="col-md-6">
<div class="country">
<div class="grid">
<div class="row">
<div class="col-sm-3 event date">{{event.start_date.day}}</div>
<div class="col-sm-6 event month">{{event.start_date.month}}</div>
</div>
<div class="row event">
<div class="col-sm-1">{{event.start_date.time}} </div>
<div class="col-sm-11" v-if="event.place"> 📌 {{event.place.name}} </div>
</div>
</div>
</div>
</div>
</div>
<h3 class="mb-30">{{event.title}}</h3>
<div class="row">
<div class="col-md-3">
<b-img v-bind:src="event.poster_link" alt="" width="200" height="200" fluid>
</div>
<div class="col-md-9 mt-sm-20">
<p>{{event.short_description}}</p>
<b-btn variant="outline-success" v-on:click="currentEvent=event;modalShow=true"> 👁 Подробнее</b-btn>
</div>
</div>
</div>
main.js
var app = new Vue({
el: '#app',
data: {
api: 'http://127.0.0.1:8000/api/events',
show: true,
events: [],
currentEvent: Object,
modalShow: false,
loading: true,
errored: false,
selected_filter: ["1", "2", "3"],
selected_date: "today",
},
computed: {
filteredEvents() {
var sel_filter = this.selected_filter
var objs = this.events.filter(function(event) {
return sel_filter.indexOf(event.type.id.toString()) >= 0
})
console.log(objs.length, sel_filter)
return objs;
}
},
mounted() {
this.getEventsFromServer();
},
methods: {
getEventsFromServer(date = (new Date).toString()) {
axios
.get(this.api)
.then(response => {
this.events = handleResponse(response)
})
.catch(error => {
console.log(error);
this.errored = true;
})
.finally(() => (this.loading = false));
},
setCurrentDateFilter: function(e) {
console.log(e)
console.log(this.selected_date)
this.getEventsFromServer();
},
},
filters: {}
})
function handleResponse(response) {
var events = []
for (let i = 0; i < response.data.length; i++) {
let e = response.data[i]
let start_date = new Date(e.start_date)
let el = {
start_date: {
day: start_date.getDate(),
time: start_date.getHours() + ":" + (start_date.getMinutes() < 10 ? '0' : '') + start_date.getMinutes(),
month: getMonthWord(start_date)
},
title: e.id,
title: e.title,
description: e.description,
short_description: e.short_description,
poster_link: e.poster_link,
source_link: e.source_link,
type: getStyledType(e.type),
phone: e.phone,
email: e.email,
place: e.place
}
events.push(el)
}
return events;
}

Categories