Filtering with Vuejs w/ axios - vuejs2

Hoping someone can point me in the right direction - I'm fairly new to Vuejs and have taken over someone else's code, although I've managed to do a fair bit without any issues, i'm struggling to get the filtering to work.
Here is the majority of the code:
<template>
<div v-if="showProperties">
<div v-if="properties.length > 0">
<div class="row">
<div class="col-2 listings--filter">
<select v-model="filter" class="form-control listings--filter_select">
<option value="" disabled hidden>Filter</option>
<option value="price-lowest">Lowest Price First</option>
<option value="price-highest">Highest Price First</option>
<option value="listing-new">Newest Listing First</option>
<option value="listing-old">Oldest Listing First</option>
</select>
</div>
<div class="col-2 listings--filtersstc">
<toggle-button v-model="sstcBtn"
:value="true"
:labels="{checked: 'Show SSTC', unchecked: 'Hide SSTC'}"
:width="120"
:height="40"/>
</div>
</div>
<div class="row margin-bottom">
<div class="col listings--filter">
<small v-show="showRemoveFilter">Current filter: {{ selectedFilter }}</small>
</div>
<div class="col listings--filter">
<small v-show="showRemoveFilter" v-on:click="removeSortProperties" class="float-right">Remove filter</small>
</div>
</div>
<div class="row">
<property-listings v-for="(property, index) in properties" v-bind:property="property" v-bind:key="index"></property-listings>
</div>
</div>
<div v-else>
<div class="row">
<div class="col text-center">
<p class="dark-text">No properties match your search criteria. Please try again.</p>
</div>
</div>
</div>
</div>
</template>
<script>
import PropertyListings from './PropertyListings.vue'
import * as VueGoogleMaps from 'vue2-google-maps'
import ToggleButton from 'vue-js-toggle-button'
Vue.use(ToggleButton)
Vue.use(VueGoogleMaps, {
load: {
key: '-------------------',
libraries: 'places', // This is required if you use the Autocomplete plugin
// OR: libraries: 'places,drawing'
// OR: libraries: 'places,drawing,visualization'
// (as you require)
}
})
export default {
data () {
return {
showProperties: false,
properties: [],
filter: '',
sstcBtn: true,
selectedFilter: '',
showRemoveFilter: false,
center: {lat: 00000, lng: -000000},
propertyInfoName: '',
propertyInfoPrice: '',
propertyInfoLink: '',
propertyInfoType: '',
infoWindowPos: {
lat: 0,
lng: 0
},
infoWinOpen: false,
currentMidx: null
}
},
delimiters: ['<%', '%>'],
components: {
PropertyListings
},
watch: {
filter: function(newFilter, oldFilter) {
this.sortProperties(newFilter);
},
sstcBtn: function(newSstcBtn, oldSstcBtn) {
this.removeSstcProperties(newSstcBtn);
}
},
methods: {
sortProperties: _.debounce(
function(newFilter) {
if(newFilter === 'price-highest') {
this.properties = _.orderBy(this.properties, 'price', 'desc')
this.selectedFilter = 'Highest Price First'
} else if(newFilter === 'price-lowest') {
this.properties = _.orderBy(this.properties, 'price', 'asc')
this.selectedFilter = 'Lowest Price First'
} else if(newFilter === 'listing-new') {
this.properties = _.orderBy(this.properties, 'id', 'desc')
this.selectedFilter = 'Newest Listing First'
} else if(newFilter === 'listing-old') {
this.properties = _.orderBy(this.properties, 'id', 'asc')
this.selectedFilter = 'Oldest Listing First'
}
this.showRemoveFilter = true
},
500
),
removeSstcProperties: _.debounce(
function(newSstcBtn) {
if(newSstcBtn == true){
console.log('do not filter')
//this.properties = _.filterBy(this.properties, 'status_id', '1')
return this.properties.filter(function(property){
return property.status_id == "1"
}.bind(this))
} else if(newSstcBtn == false){
console.log('do filter')
}
},
500
),
removeSortProperties: function() {
this.properties = _.orderBy(this.properties, 'id', 'desc')
this.showRemoveFilter = false
},
toggleInfoWindow: function(property, idx) {
this.infoWindowPos = {lat: Number(property.latitude), lng: Number(property.longitude)}
this.propertyInfoName = property.display_address
this.propertyInfoPrice = property.price
if(property.let_type_id === '3') {
this.propertyInfoLink = '/properties/for-students/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
} else if(jQuery.inArray(property.let_type_id, ['1','2']) != '-1'){
this.propertyInfoLink = '/properties/for-rent/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
} else {
this.propertyInfoLink = '/properties/for-sale/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
}
}
},
created() {
var self = this;
axios.get('/properties/json')
.then(function (response) {
self.properties = response.data
self.showProperties = true
})
.catch(function (error) {
console.log(error);
});
}
}
</script>
Everything else is working fine but the bit i've been working on is the removeSstcProperties method, I've got the method triggering fine, however I'm struggling to actually filter the results for properties that have the status_id = 1. I've tried 2 ways (one commented out). Can anyone point me in the right direction?

Related

vuejs checkbox need to change method

I have a dropdown menu that triggers a method to get data based on what is selected in the dropdown. I would like to add a condition that changes the #change method if a checkbox is selected. The method would switch based on which checkbox is selected. I guess a v-if that runs a check somewhere--Im not sure.
new Vue({
el: "#app",
data: {
selection: 'Select a option',
todos: [{
name: 'apple'
}, {
name: 'oranges'
}, {
name: 'carrots'
}]
},
methods:{
changeP (event) {
this.getSetA();
// alert("this is set a");
},
changeP1 (event) {
this.getSetB();
alert("this is set b");
},
changeP2 (event) {
this.getSetC();
alert("this is set c");
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Fruit:</h2>
<select v-model="selection" #change="changeP($event)">
<option value="Select a option" disabled>Choose an fruit:</option>
<option v-for="(t, i) in todos" :key="i" :value="t.name">{{ t.name }}</option>
</select>
<br>
<input type="checkbox" id="vehicle1" name="vehicle1" value="apple"> Apples
<input type="checkbox" id="vehicle2" name="vehicle2" value=""> Oranges
<input type="checkbox" id="vehicle3" name="vehicle3" value="">pears
</div>
new Vue({
el: '#app',
data: {
selection: 'Select an option',
selectOptions: [ { name: 'apple' }, { name: 'oranges' }, { name: 'carrots' }],
checkboxOptions: [ 'vehicle1', 'vehicle2', 'vehicle3' ],
checkedItems: [],
message: '',
},
methods: {
onDropdownChange() {
this.message = '';
if (this.checkedItems.length) {
this.message = `You've selected: `;
for(let i = 0; i < this.checkedItems.length; i++) {
this.message += this.checkedItems[i] + ' ';
}
}
switch(this.selection) {
case 'apple':
return this.onAppleSelected();
case 'oranges':
return this.onOrangesSelected();
default:
return this.onCarrotsSelected();
}
},
onAppleSelected() {
if (this.message.length) {
this.message += 'and apple.';
return;
}
this.message = `You've selected apple`;
},
onCarrotsSelected() {
this.message += ' CARROT!'
},
onOrangesSelected() {
this.message += ' No Scurvy';
}
},
template: `
<div id="app">
<h2>Fruit:</h2>
<select v-model="selection" #change="onDropdownChange">
<option value="Select an option">Choose</option>
<option v-for="(o, i) in selectOptions" :key="o.name" :value="o.name">{{o.name}}</option>
</select>
<div style="display:block" v-for="(o, i) in checkboxOptions" :key="o">
<label :for="o">{{o}}</label>
<input type="checkbox" :id="o" :name="o" :value="o" v-model="checkedItems" />
</div>
<p>{{message}}</p>
</div>
`
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
</div>
You should probably have a single method that decides which method to call based on the state of the component.

radio checked between 2 values

I am modifying a module on Prestashop (Blockwishlist) which uses VueJS and I want to add the available combinations in the customers' wish list in order to be able to select a combination and add it to the cart.
But I'm stuck on a part when loading the page: I get the id_product and the id_product_attribute and I also loop on all the variations of the product.
I am looking for a checked radio button by comparing the values ​​of my loop and the id_product_attribute value that I get back and if it exists in my loop this checked the radio button.
This is what my vuejs code looks like now (with attempts that don't work)
<template>
<div class="wishlist-product">
<a
class="wishlist-product-link"
:href="product.canonical_url"
>
<div class="wishlist-product-image">
<img
v-if="product.default_image"
:src="product.default_image.large.url"
:alt="product.default_image.legend"
:title="product.default_image.legend"
:class="{
'wishlist-product-unavailable': !product.add_to_cart_url
}"
>
<img
v-else
:src="prestashop.urls.no_picture_image.bySize.home_default.url"
>
</div>
<div class="wishlist-product-right">
<p class="wishlist-product-title">{{ product.name }}</p>
<p class="wishlist-product-price">
<span
class="wishlist-product-price-promo"
v-if="product.has_discount"
>
{{ product.regular_price }}
</span>
{{ product.price }}
</p>
<div class="wishlist-product-combinations">
<div class="product-variants">
<div class="clearfix product-variants-item">
<div id="group_1" class="radio">
<div v-for="(attribute, key, index) of product.all_attributes" class="input-container float-xs-left"
:class="{'no_stock_variant' : attribute.quantity <= 0}">
<label>
<input
#change="changeAttribute($event)"
v-model="id_product_attribute"
name="id_product_attribute"
class="input-radio" type="radio"
:data-id-product=attribute.id_product
:data-id-product-attribute=attribute.id_product_attribute
:data-product-attribute=attribute.id_attribute
:value="key"
v-if="checkedId(attribute.id_product_attribute) ? 'checked=checked' : ''"
:title=attribute.attribute_name>
<div class="content">
<span class="radio-label">
{{ attribute.attribute_name }}
<img v-if="attribute.quantity <= 0"
:src="imgEnveloppe"
:class="{hover: isHovering}"
#mouseover="imgEnveloppe = imgRing"
#mouseout="isHovering = false"
:alt="attribute.attribute_name"
>
</span>
</div>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
<div class="wishlist-product-bottom">
<button
class="btn btn-indies-gold wishlist-button-add"
v-if="!isShare"
#click="removeFromWishlist"
>
{{ deleteText }}
</button>
<button
class="btn btn-indies wishlist-product-addtocart"
:disabled="isDisabled"
#click="
product.add_to_cart_url || product.customizable === '1'
? addToCartAction()
: null
"
>
{{ product.customizable === '1' ? customizeText : addToCart }}
</button>
</div>
<p
class="wishlist-product-availability wishlist-product-availability-responsive"
v-if="product.show_availability"
>
<i
class="material-icons"
v-if="product.availability === 'unavailable'"
>
block
</i>
<i
class="material-icons"
v-if="product.availability === 'last_remaining_items'"
>
warning
</i>
{{ product.availability_message }}
</p>
</div>
</template>
<script>
import EventBus from '#components/EventBus';
import headers from '#constants/headers';
import prestashop from 'prestashop';
import wishlistAddProductToCartUrl from 'wishlistAddProductToCartUrl';
export default {
name: 'Product',
props: {
product: {
type: Object,
required: true,
default: null,
},
deleteText: {
type: String,
required: true,
},
imgEnveloppe: {
type: String,
required: true,
},
imgRing: {
type: String,
required: true,
},
listId: {
type: Number,
required: true,
default: null,
},
isShare: {
type: Boolean,
required: false,
default: false,
},
customizeText: {
type: String,
required: true,
default: 'Customize',
},
quantityText: {
type: String,
required: true,
default: 'Quantity',
},
addToCart: {
type: String,
required: true,
},
status: {
type: Number,
required: false,
default: 0,
},
hasControls: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
prestashop,
isHovering: false,
id_product_attribute: null
};
},
computed: {
isDisabled() {
if (this.product.customizable === '1') {
return false;
}
return !this.product.add_to_cart_url;
},
},
methods: {
checkedId (idProductAttribute) {
if (this.product.id_product_attribute === parseInt(idProductAttribute)) {
console.log(idProductAttribute);
return true;
}
return false;
},
changeAttribute(e) {
this.id_product_attribute = e.target.getAttribute('data-id-product-attribute');
},
/**
* Remove the product from the wishlist
*/
async removeFromWishlist() {
EventBus.$emit('showDeleteWishlist', {
detail: {
listId: this.listId,
productId: this.product.id,
productAttributeId: this.product.id_product_attribute,
},
});
},
async addToCartAction() {
if (this.product.add_to_cart_url && this.product.customizable !== '1') {
try {
const datas = new FormData();
datas.append('qty', this.product.wishlist_quantity);
datas.append('id_product', this.product.id_product);
datas.append('id_product_attribute', this.id_product_attribute);
datas.append('id_customization', this.product.id_customization);
const response = await fetch(
`${this.product.add_to_cart_url}&action=update`,
{
method: 'POST',
headers: headers.addToCart,
body: datas,
},
);
const resp = await response.json();
prestashop.emit('updateCart', {
reason: {
idProduct: this.product.id_product,
idProductAttribute: this.id_product_attribute,
idCustomization: this.product.id_customization,
linkAction: 'add-to-cart',
},
resp,
});
/* eslint-disable */
const statResponse = await fetch(
`${wishlistAddProductToCartUrl}&params[idWishlist]=${this.listId}&params[id_product]=${this.product.id_product}&params[id_product_attribute]=${this.id_product_attribute}&params[quantity]=${this.product.wishlist_quantity}`,
{
headers: {
'Content-Type':
'application/x-www-form-urlencoded; charset=UTF-8',
Accept: 'application/json, text/javascript, */*; q=0.01'
}
}
);
/* eslint-enable */
await statResponse.json();
} catch (error) {
prestashop.emit('handleError', {
eventType: 'addProductToCart',
resp: error,
});
}
} else {
window.location.href = this.product.canonical_url;
}
},
},
};
Thank you for help.

How to make disabled button after click in Vuejs

I have a button on my website that gives bonuses to the user. Button have several conditions in 1 button:
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
<script>
......
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
.......
</script
But when user click Take button, and if all success, button is still active this.$forceUpdate(); not working. And i need make when user click Take button, and if all success, make this button disabled.
My full Bonus.vue:
<template>
<div class="inner-page">
<div class="account" v-if="loaded && !$root.isMobile">
<div class="page-header">
</div>
<div class="form-panels hide-below-m">
<div class="col-7" style="margin-top: 5rem;margin-right: 3rem;">
<div class="faucet-component mx-5" rv-class-boost="data.boostIsOpen">
<img src="https://dota2.skins1.games/src/img/components/shine.png?v=8ce59643e70cb2f8550deb6a249b5f29" class="faucet-component__shine-bg">
<div class="faucet-component__content d-flex justify-content-between align-items-center flex-column w-100" style="
height: 15rem;">
<div class="faucet-component__available-amount-block round-circle p-2">
<div class="faucet-component__availabe-amount-coins d-flex justify-content-center align-items-center round-circle h-100" rv-currency="model:amount">Спасение</div>
</div>
<!-- rivets: unless model:cnt | eq 0 --><div class="faucet-component__remaining">
<span rv-t="">Left</span>:
<span>{{ bonus_num }}</span><br>
<span rv-t=""></span>
<span>{{ diff }}</span>
</div>
<!-- rivets: if model:cnt | eq 0 -->
<div class="faucet-component__buttons-container d-flex align-items-center w-75 justify-content-around">
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
loaded: false,
bonus: {},
diff: {},
user: {},
bonus_num: 0,
heal_used: {}
}
},
mounted() {
this.$root.isLoading = true;
if (!this.$cookie.get('token')) {
this.$root.isLoading = false;
this.$router.go(-1);
}
this.domain = window.location.protocol + '//' + window.location.hostname;
setTimeout(() => {
this.getUser();
}, 100);
},
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
methods: {
getUser() {
this.$root.axios.post('/user/getProfile')
.then(res => {
const data = res.data;
console.log(data.heal_used);
console.log(data.diff);
this.loaded = true;
this.user = data.user;
this.bets = data.bets;
this.bonus = data.bonus;
this.diff = data.diff;
this.heal_used = data.heal_used;
this.new_day = data.new_day;
this.bonus_num = data.bonus_num;
this.$root.isLoading = false;
})
.catch(err => {
this.$root.isLoading = false;
this.$router.go(-1);
})
},
takeBonus() {
this.$root.axios.post('/user/takeBonus', {
value: this.user.cashback
})
.then(res => {
const data = res.data;
if (data.type === 'success') {
console.log(data.heal_used);
this.bonus_num = data.bonus_num;
this.$root.user.balance = data.newBalance;
this.heal_used = data.heal_used;
this.$forceUpdate();
}
this.$root.showNotify(data.type, this.$t(`index.${data.message}`));
})
},
}
}
How i can make it, when user click Take button, and if all success, so that the Take button becomes disabled?
I'm sorry but your code has no indentation, so I just did that on jsfiddler so you know "How to make disabled button after click in Vuejs". You can have a look on : https://jsfiddle.net/o81yvn05/1/
<div id="app">
<button :disabled="isDisabled" #click="disableButton()">Please click here</button>
</div>
<script>
new Vue({
el: "#app",
data: {
isDisabled: false,
},
methods: {
disableButton() {
this.isDisabled = true
}
}
})
</script>

Vue el-form dynamic validation

<template>
<div>
<el-form label-position="top" :model="notificationEmails" ref="emailForm">
<el-form-item
v-for="(item, index) in notificationEmails.emails"
:key="index"
:label="getLabel(index)"
:for="`${item.id}_${index}`"
:prop="'emails.' + index + '.id'"
:rules="{
required: true,
type: 'email',
message: 'Not valid email',
trigger: ['blur', 'change']
}"
>
<el-row>
<el-col :span="6">
<el-input v-model="item.id" type="email" :id="`${item.id}_${index}`" />
</el-col>
<el-col :span="2" style="padding-left: 18px">
<span v-if="index === 0" tabindex="0" #click="addEmail" #keyup.enter.stop="addEmail">
<i aria-hidden="true" class="icon-add-circle-outline" />
<span class="screen-reader">{{$t('a11y.settings.soldTo.notif.action.addEmail')}}</span>
</span>
<span
v-else
tabindex="0"
#click="deleteEmail(item.id)"
#keyup.enter.stop="deleteEmail(item.id)"
>
<i class="icon-subtract-circle-outline" aria-hidden="true" />
<span class="screen-reader">{{$t('a11y.settings.soldTo.notif.action.deleteEmail')}}</span>
</span>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'EmailWidget',
data() {
return {
notificationEmails: {
emails: []
}
};
},
props: ['passEmail'],
watch: {
passEmail: {
handler(newVal) {
this.notificationEmails.emails = newVal;
},
deep: true
},
notificationEmails: {
handler() {
this.$refs.emailForm.validate(async validate => {
if (validate) {
await this.$store.dispatch('settings/GENERIC', {
module: 'common',
propKey: 'validEmail',
propValue: true
});
} else {
await this.$store.dispatch('settings/GENERIC', {
module: 'common',
propKey: 'validEmail',
propValue: false
});
}
});
},
deep: true
}
},
methods: {
addEmail() {
this.notificationEmails.emails.push({
id: '',
priority: this.notificationEmails.emails.length + 1
});
// this.emails = [...this.emails, { id: '', priority: this.emails.length + 1 }];
},
deleteEmail(email) {
// this.emails = this.emails.filter(item => item.id !== email);
let index = 0;
for (let i = 0; i < this.notificationEmails.emails.length; i += 1) {
if (this.notificationEmails.emails[i].id === email) {
index = i;
break;
}
}
this.notificationEmails.emails.splice(index, 1);
},
getLabel(index) {
return index === 0 ? this.$t('settings.soldTo.notif.email') : '';
}
},
};
</script>
<style lang="scss">
i:hover {
cursor: pointer;
}
</style>
Some problems about the validation in dynamic add or delete the emails in el-form of Vue. When I add a new email, the validation cannot work. When I delete email. it shows
Error: please transfer a valid prop path to form item!
There is no issue when I edit the email.
I change the props according to enter code here the official document, but it still shows error.

Getting a single array from an array of object

I am trying to iterate through the array of object called sources at change event of my select input then pushing this single array to a new element conditionally
<template>
<div class="sourceselection">
<div class="jumbotron">
<h2><span class="glyphicon glyphicon-list"></span> News List</h2>
<h4>Select News Source</h4>
<select class="form-control" #change="sourceChanged">
<option v-bind:value="source.id" v-for="source in sources" :key="source.id">{{source.name}}</option>
</select>
</div>
<div v-if="source">
<h6 >{{source.description}}</h6>
<a v-bind:href="source.url"></a>
</div>
</div>
</template>
<script>
export default {
name: 'SourceSelection',
data () {
return {
sources: [],
source: '',
}
},
methods: {
sourceChanged (event) {
for (var i = 0; i < this.sources.length; i++){
if (this.sources[i].id == event.target.value){
this.source = this.sources[i];
}
}
}
},
created : function () {
this.$http.get('https://newsapi.org/v2/sources?language=en&apiKey=cf0866b5aaef42e995f9db37bb3f7ef4')
.then(response => {
this.sources = response.data.sources;
})
.catch(error => console.log(error));
}
}
</script>
i expect to pull the description into my h6 if the source exist
At first create a state in data and name it sourceId,
then bind it to select <select v-model="sourceId" class="form-control">.
Now we need a computed filed which returns the source return this.sources.find(s => s.id === this.sourceId)
<template>
<div class="sourceselection">
<div class="jumbotron">
<h2><span class="glyphicon glyphicon-list"></span> News List</h2>
<h4>Select News Source</h4>
<select v-model="sourceId" class="form-control">
<option v-for="source in sources" :value="source.id" :key="source.id">
{{ source.name }}
</option>
</select>
</div>
<div v-if="source">
<h6 >{{ source.description }}</h6>
<a v-bind:href="source.url"></a>
</div>
</div>
</template>
<script>
export default {
name: 'SourceSelection',
data () {
return {
sources: [],
sourceId: ''
}
},
computed: {
source () {
return this.sources.find(s => s.id === this.sourceId)
}
},
created() {
this.$http.get('https://newsapi.org/v2/sources?language=en&apiKey=cf0866b5aaef42e995f9db37bb3f7ef4')
.then(response => {
this.sources = response.data.sources;
})
.catch(error => console.log(error));
}
}
</script>
Instead of using an event handler you can bind the selected value directly to your source data.
here is a demo:
Vue.config.devtools = false
Vue.config.productionTip = false
new Vue({
el: '#app',
data() {
return {
sources: [{
id: '1',
description: 'one desc',
name: 'one'
}, {
id: '2',
description: 'two desc',
name: 'two'
}, ],
source: ''
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select class="form-control" v-model="source">
<option v-bind:value="source" v-for="source in sources" :key="source.id">{{source.name}}</option>
</select>
<h6>{{ source.description }}</h6>
</div>