link1507 link1508 link1509 link1510 link1511 link1512 link1513 link1514 link1515 link1516 link1517 link1518 link1519 link1520 link1521 link1522 link1523 link1524 link1525 link1526 link1527 link1528 link1529 link1530 link1531 link1532 link1533 link1534 link1535 link1536 link1537 link1538 link1539 link1540 link1541 link1542 link1543 link1544 link1545 link1546 link1547 link1548 link1549 link1550 link1551 link1552 link1553 link1554 link1555 link1556 link1557 link1558 link1559 link1560 link1561 link1562 link1563 link1564 link1565 link1566 link1567 link1568 link1569 link1570 link1571 link1572 link1573 link1574 link1575 link1576 link1577 link1578 link1579 link1580 link1581 link1582 link1583 link1584 link1585 link1586 link1587 link1588 link1589 link1590 link1591 link1592 link1593 link1594 link1595 link1596 link1597 link1598 link1599 link1600 link1601 link1602 link1603 link1604 link1605 link1606 link1607 link1608 link1609 link1610 link1611 link1612 link1613 link1614 link1615 link1616 link1617 link1618 link1619 link1620 link1621 link1622 link1623 link1624 link1625 link1626 link1627 link1628 link1629 link1630 link1631 link1632 link1633 link1634 link1635 link1636 link1637 link1638 link1639 link1640 link1641 link1642 link1643

[Vue.js] Can I move my web app Vuejs to NativeScript-Vue?

Good,
My question is really simple. there is a web project made in Vuejs and I would like to know if there is any way to take this project and to mirror it to NativeScript-vue.js in some way.

Thanks and best regards!

Solution :

There isn’t an automated way to migrate the app. The templates should be completely rewritten as the mobile world has different UI components and concepts. the scripts and styles, for the most part, should work the same way. You will need to figure out how to do the routing as the default vue.js router is not supported. You can check the manual routing article fore more information.

[Vue.js] Execute method after all promises inside of a given method resolved

In a Vue.js component, there is some methods that use axios to call an API.

In different cases, I need to execute some code once the call in this method has resolved, but I don’t want to add a bunch of if statements in the .then() chained to the axios call.

methods: {
callApi() {
axios.get(‘/api’)
.then(() => {
// call has resolved, request is done
})
},
firstMethod() {
this.callApi()
// Need to wait for the call to resolve
// Do something
},
secondMethod() {
this.callApi()
// Need to wait for the call to resolve
// Do something else
}
}

As you can see, firstMethod and secondMethod both rely on callApi but are supposed to do a different thing once the request is done. I prefer to split this logic in different functions instead of using conditions in the callApi method.
Is there a way to do this without having to add this logic inside of the
callApi ?

Solution :

Have callApi return the promise chain, then use and return that in firstMethod and secondMethod.

methods: {
callApi() {
return axios.get(‘/api’)
.then(() => {
// call has resolved, request is done
})
},
firstMethod() {
return this.callApi()
.then(() => {
// Need to wait for the call to resolve
// Do something
})
},
secondMethod() {
return this.callApi()
.then(() => {
// Need to wait for the call to resolve
// Do something else
})
}
}

Whatever calls callApi, firstMethod, or secondMethod should check for failure and handle/report it.

the original code was breaking one of the rules of promises: The function should always either return the chain, or handle rejection. (And yes, that’s or [99.9% of the time], not and.)

Solution 2:

Promises chain, so you need to take the promise that Axios returns, perform any handling you might need to do, then return it from the callApi method. In the other methods where you’re calling callApi you handle the returned promise and put any code that has to run after the API has responded in the handler function.

callApi() {
return axios.get(‘/api’)
.then(() => {
// this gets handled first
})
},
firstMethod() {
this.callApi()
.then(() => {
// this gets handled second
})
},
secondMethod() {
this.callApi()
.then(() => {
// or this gets handled second
})
}

[Vue.js] Accessing Vue.$router inside an external service class

there is a service which extends EventEmitter.

services/service/service.js (relative to main.js)

import { EventEmitter } from “events”;

class Service extends EventEmitter {}

Inside the Service class, there is the following method which returns a Promise:

/**
* Method to fetch the Active Survey by “surveySlug”:
*/
fetchActiveSurvey(serviceSlug) {
return new Promise((resolve, reject) => {
axios.get(`${this.baseURL}/service/${serviceSlug}`, { headers: { Authorization: AuthStr } }).then(response => {
resolve(response.data);
}).catch(error => {
if (error.response && error.response.data.status != 200) {
Vue.$router.push({ name: ‘home’});
}
});
});
}

I also have the usual routes.js in the same directory as main.js, which is working fine.

Services are then established as plugins:

import Service from “../services/service/service”; // <= Refrences `service.js`

export default {
install(Vue) {
Vue.prototype.$service = Service;
}
};

there is tried the following:

Vue.$router.push({ name: ‘home’});

Vue.prototype.$router.push({ name: ‘home’});

However, I seem to find that $router is not defined. What would be the best way to define the router push routes from inside this service?

Solution :

You need to use the this keyword to access the router instance. Try:

this.$router.push({ name: ‘home’});

[Vue.js] select all method for checkboxes , should not select disabled checbox in vue.js

there is a list with checkboxes in the table , when i click select all function , it selects all checkbox including disabled ones, i neeed to exclude the disabled checkbox .

<li><a @click.prevent=”selectAll” id=”cardSelectAllAId”>
SelectAll</a></li>

<single-checkbox class=”checkbox “
inputId=”card.data.id”
v-if=”card.data.id”
@change=”change(card.data)”
:value=”card.data.selected”
:disabled=”!card.data.licenseEnabled”>

selectAll() {
for (let i = 0; i < this.cards.length; i += 1) {
if (this.cards[i].selected !== undefined) {
this.cards[i].selected = true;
}
},

Solution :

You can try something like this in the function-

// Reset all selected first
this.cards.map((x) => x.selected = false);
// Filter and then set selected to true
this.cards
.filter((x) => x.data.licenseEnabled)
.map((x) => x.selected = true);

[Vue.js] Vee-Validation for unique email address

when storing emails in an array called ‘emailsDB’ and trying to check if the email being entered by the user in the email input field exists in the array.

The exact steps that there is followed are provided here - https://www.npmjs.com/package/vee-validate

However, on implementation I get an error in the console which says -

SyntaxError: import declarations may only appear at top level of a
module

HTML code

<div id=”updateName” class=”wrapper wrapper-right”>
<div class=”wrapper-inner full-height”>
<!–Contact Sec–>
<section>
<!–form sec–>
<section class=”animated container-fluid align-center sec-ptop”>
<h3 class=”salutation”>
Hey <span v-if=’formData.Name.length’>{formData.Name}</span> <span v-else>There</span>, happy to hear from you.
</h3>
<div>
<form v-on:submit.prevent=”validateBeforeSubmit” name=”contactform” method=”post” class=”row form-horizontal” role=”form” novalidate=”true”>
<div class=”form-group input–josh col-6”>
<div class=”input-wrap”>
<input autocomplete=”off” type=”text” v-model=”formData.Name” v-validate=”‘required’” id=”Name” name=”Name” placeholder=”Name” class=”form-control input__field input input__field–josh” :class=”{‘input’: true, ‘is-danger’: errors.has(‘Name’) }” />
<i v-show=”errors.has(‘Name’)” class=”fa fa-exclamation”></i>
<label for=”Name” class=”input__label input__label input__label–josh input__label–josh-color-1 input__label–josh input__label–josh-color-1”></label>
</div>
<span v-show=”errors.has(‘Name’)” class=”help is-danger”>{ errors.first(‘Name’) }</span>
</div>
<div class=”form-group input–josh col-6”>
<div class=”input-wrap”>
<input autocomplete=”off” type=”email” v-model=”formData.Email” v-validate=”‘required|email’” id=”Email” name=”Email” placeholder=”Email” class=”form-control input input__field input__field–josh” :class=”{‘input’: true, ‘is-danger’: errors.has(‘Email’) }”>
<i v-show=”errors.has(‘Email’)” class=”fa fa-exclamation”></i>
<label for=”Email” class=”input__label input__label–josh input__label–josh-color-1”></label>
</div>
<span v-show=”errors.has(‘Email’)” class=”help is-danger”>{ errors.first(‘Email’) }</span>
</div>
<div class=”form-group input–josh col-12”>
<div class=”input-wrap”>
<textarea rows=”4” v-model=”formData.Message” v-validate=”‘required’” id=”Message” name=”Message” placeholder=”message” class=”form-control input input__field input__field–josh” :class=”{‘input’: true, ‘is-danger’: errors.has(‘Message’) }”></textarea>
<i v-show=”errors.has(‘Message’)” class=”fa fa-exclamation”></i>
<label for=”Message” class=”input__label input__label–josh input__label–josh-color-1”></label>
</div>
<span v-show=”errors.has(‘Message’)” class=”help is-danger”>{ errors.first(‘Message’) }</span>
</div>
<div class=”form-group col-12”>
<div class=”align-center”>
<button type=”submit” class=”btn btn-default” data-ng-disabled=”submitButtonDisabled”>
<span class=”mask”></span>
send
</button>
</div>
</div>
</form>
</div>
</section>
<!–/Contact Sec–>
</div>
</div>

vue.js code

Vue.use(VeeValidate);
import { ValidationProvider } from ‘vee-validate’;
Vue.config.productionTip = false;
Vue.component(‘ValidationProvider’, ValidationProvider);
const emailsDB = [“viveks.nair1988@gmail.com“];

var app = new Vue({
el: ‘#updateName’,
mounted() {
const isUnique = value =>
new Promise(resolve => {
setTimeout(() => {
if (emailsDB.indexOf(value) === -1) {
return resolve({
valid: true
});
}
return resolve({
valid: false,
data: {
message: `${value} has already reached out to me!`
}
});
}, 200);
});
Validator.extend(“unique”, {
validate: isUnique,
getMessage: (field, params, data) => data.message
});
}
})

Working example -
https://codesandbox.io/s/y3504yr0l1?initialpath=%2F%23%2Fbackend&module=%2Fsrc%2Fcomponents%2FBackend.vue

Image of what the result should be:
How the implementation should work

Solution :

The error import declarations may only appear at top level of a module means that when you use import in a script, no other instruction may appear before.

So, you need to move the Vue.use(VeeValidate); line after any import(s):

import { ValidationProvider } from ‘vee-validate’;
Vue.use(VeeValidate);
Vue.config.productionTip = false;
Vue.component(‘ValidationProvider’, ValidationProvider);
const emailsDB = [“viveks.nair1988@gmail.com“];

This has nothing to do with vee-validate itself.

[Vue.js] Is there a better way to change button display in javascript/Vue?

After writing so many if else, I feel very tired. I’m using Vue. The following code are written in the script section of the vue.js file. I get a json from file, and then read the values in json, then set what button should be display based on employee level and on application status. Is there a better way to change the button display status in Vue?

if (
(this.GLOBAL2.jsonForGlobal.employeeLevel == “1” &&
(this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Checking” ||
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Pending” ||
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Approved”)) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “2” &&
(this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Pending” ||
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Approved”)) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “3” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Approved”)
) {
this.pullDisplay = true;
} else {
this.pullDisplay = false;
};

if (
this.GLOBAL2.jsonForGlobal.employeeLevel == “1” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Revising”
) {
this.cancelDisplay = true;
} else {
this.cancelDisplay = false;
};

if (
(this.GLOBAL2.jsonForGlobal.employeeLevel == “1” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Revising”) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “2” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Checking”) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “3” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Pending”)
) {
this.saveDisplay = true;
} else {
this.saveDisplay = false;
};

if (
this.GLOBAL2.jsonForGlobal.employeeLevel == “1” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Revising”
) {
this.reviseDisplay = true;
} else {
this.reviseDisplay = false;
};

if (
(this.GLOBAL2.jsonForGlobal.employeeLevel == “2” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Checking”) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “3” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Pending”)
) {
this.sendDisplay = true;
} else {
this.sendDisplay = false;
};

if (
(this.GLOBAL2.jsonForGlobal.employeeLevel == “3” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Pending”) ||
(this.GLOBAL2.jsonForGlobal.employeeLevel == “2” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus == “Checking”)
) {
this.approvalDisplay = true;
} else {
this.approvalDisplay = false;
};

And also there are a few ones need three conditions:

if (
this.GLOBAL2.jsonForGlobal.employeeLevel == “3” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].requestCategory ==
“External Request” &&
this.GLOBAL2.jsonForGlobal.detail[this.detailId].currentStatus ==
“Pending”
) {
this.returnDisplay = true;
} else {
this.returnDisplay = false;
}

Solution :

Going with a configuration based approach will make the code much more easy to edit and to read.

const levels = {
‘1’: {
pullDisplayStatus: [‘Checking’, ‘Pending’, ‘Approved’],
cancelDisplayStatus: [‘Revising’],
saveDisplayStatus: [‘Revising’],
reviseDisplayStatus: [‘Revising’],
sendDisplayStatus: [],
approvalDisplayStatus: [],
},
‘2’: {
pullDisplayStatus: [‘Pending’, ‘Approved’],
cancelDisplayStatus: [],
saveDisplayStatus: [‘Checking’],
reviseDisplayStatus: [],
sendDisplayStatus: [‘Checking’],
approvalDisplayStatus: [‘Checking’],
},
‘3’: {
pullDisplayStatus: [‘Approved’],
cancelDisplayStatus: [],
saveDisplayStatus: [‘Pending’],
reviseDisplayStatus: [],
sendDisplayStatus: [‘Pending’],
approvalDisplayStatus: [‘Pending’],
},
}

const jsonForGlobal = this.GLOBAL2.jsonForGlobal;
const currentStatus = jsonForGlobal.detail[this.detailId].currentStatus;
const level = levels[jsonForGlobal.employeeLevel];
this.pullDisplay = level.pullDisplayStatus.indexOf(currentStatus) > -1;
this.cancelDisplay = level.cancelDisplayStatus.indexOf(currentStatus) > -1;
this.saveDisplay = level.cancelDisplayStatus.indexOf(currentStatus) > -1;
this.reviseDisplay = level.reviseDisplayStatus.indexOf(currentStatus) > -1;
this.sendDisplay = level.reviseDisplayStatus.indexOf(currentStatus) > -1;

Solution 2:

If you use a property often it makes sense to introduce a local variable for it to clean things up:

const { employeeLevel, detail: { [this.detailId]: { currentStatus }} = his.GLOBAL2.jsonForGlobal;

Secondly you don’t need the if / else, you can just assign the boolean:

this.pullDisplay = (
employeeLevel == “1” && [“Checking”, “Pending”, “Approved”].includes(currentStatus) ||
employeeLevel == “2” && [“Pending”, “Approved”].includes(currentStatus) ||
employeeLevel == “3” && currentStatus == “Approved”
)

[Vue.js] Use i18n tag for translating

there is an issue with my new Vuejs project, I use vuei18n in the same way like an other project of my company, but in the new project the tag doesn’t work.
When I disable silentTranslationWarn in i18n/index.js there is this messages :

[vue-i18n] Value of key ‘pages’ is not a string!
[vue-i18n] Cannot translate the value of keypath ‘pages’. Use the value of keypath as default

When I put my translations in i18n/fr.js like this, my translation works :

const messages = {
pages: ‘Pages’,
};

But when to use tag in the component, like in the old project there is the vue-i18n warns desribed before.
there is searched in the old project all occurencies of “i18n”, “local”, “messages” etc… but there is exactly the same occurency in the new project, in my package.json there is same version of vue-i18n

Did I missed something ?

Solution :

@kalidou.diagne :

In my i18n/index.js :

import vue.js from ‘vue’;
import VueI18n from ‘vue-i18n’;

import en from ‘./en’;
import fr from ‘./fr’;

Vue.use(VueI18n);
const messages = { en, fr };

export default new VueI18n({
locale: ‘fr’,
silentTranslationWarn: true,
messages,
});

In my main.js :

import i18n from ‘./i18n’;

const Mdm = Vue.component(‘app’, App);

/* eslint-disable no-new */
new Mdm({
el: ‘#app’,
i18n,
router,
store,
components: { App },
template: ‘<App/>’,
});

[Vue.js] How to limit the input length on a v-select element?

I use the Vue-select feature on my project, and in a v-select element to set up a maximum input length (45 characters), but I’m failing to do so. I managed to treat this on the back-end, but I’d like to prevent the user from inputing more than it’s allowed.

I tried to use the property :maxlength=”45” but it seems that it have absolutely no effect on the input length.

Here’s what I have:

<div class=”form-group”>
<div class=”row”>
<div class=”col-xs-8”>
<v-select taggable pushTags :maxlength=”maxlength” v-model=”lote” :options=”lotes” @input=”selecionarLote” >
<span slot=”no-options”>Digite o nome de um lote e clique “Enter” para adicionar…</span>
</v-select>
</div>
<div class=”col-xs-4”>
<label class=”control-label”>Descarte</label>
<p-switch v-model=”descarte” type=”primary” on-text=”SIM” off-text=”NO”></p-switch>
</div>
</div>
</div>

selecionarLote() {
let vm = this;
if (this.lotes.length) {
if (!this.lote || !this.lote.label) return;

if (this.lote.label.length > 45) {
this.lote.label = this.lote.label.substring(0, 45);
}

As I said, I can handle the inputs that are above 45 characters, but I’d like to prevent it, just like this code do: https://codepen.io/CSWApps/pen/RQbvvp, I searched the vue-select documentation and wasn’t able to find a way to limit the input length.

Thanks for any help in advance.

-————– EDIT ———————-

I tried to use Michael’s answer, but I could still type more than 45 characters:

data() {
return {
maxlength: [v => v.length < 45 || “Sorry you have exceeded the max length of input”],
lote: null,
descarte: false,
modelValidations: {
requiredText: {
required: true
}
}
};
}

<div class=”form-group”>
<div class=”row”>
<div class=”col-xs-8”>
<v-select taggable pushTags :rules=”maxlength” v-model=”lote” :options=”lotes” @input=”selecionarLote” >
<span slot=”no-options”>Digite o nome de um lote e clique “Enter” para adicionar…</span>
</v-select>
</div>
<div class=”col-xs-4”>
<label class=”control-label”>Descarte</label>
<p-switch v-model=”descarte” type=”primary” on-text=”SIM” off-text=”NO”></p-switch>
</div>
</div>
</div>

Solution :

You need to provide it with one of the props of v-select, In this you can use rules like this:

<v-select taggable pushTags :rules=”maxlength” v-model=”lote” :options=”lotes” @input=”selecionarLote” >
<span slot=”no-options”>Digite o nome de um lote e clique “Enter” para adicionar…</span>
</v-select>

data(){
return {
maxlength: [v => v.length < 45 || “Sorry you have exceeded the max length of input”]
}

[Vue.js] Move data from internal Vue JS file to an external JSON file

when trying to make a variant of a nice vue.js Invoicing app from Adam Wathan (Tailwind CSS founder)

to have the data in an external JSON file rather than within the vue.js JS code itself.

there is tried using the code below to get data from an external file but can’t get it to work

const app = new Vue({
data: {
taxRate: ‘’,
to: ‘’,
from: ‘’,
items: ‘’
},
created: function () {
fetch(‘https://example.netlify.com/invoicedetails.json')
.then(resp => resp.json())
.then(items => {
this.items = items
})
}
});

Here is the code needed for partial extraction of the data:

new Vue({
data: {
taxRate: .13,
to: [
‘University of Somewhere’,
‘118 Bureaucracy Lane’,
‘Cityville, CA 90210’,
],
from: [
‘Business Time Inc.’,
‘60 Paycheck Drive’,
‘Townsland, ON A1B 2CD’,
‘Canada’,
],
items: [
[1, `Amazing product you can’t live without`, 549],
[3, `Unnecessary extra item`, 49],
]
},
template: `
<div class=”min-h-screen bg-gray-700 p-8 text-gray-900”>
<div class=”max-w-4xl mx-auto”>
<div ref=”quote” class=”bg-white px-12 py-20”>
<h1 class=”uppercase font-bold text-gray-600 text-3xl border-b pb-8”>Quote</h1>
<div class=”mt-8 flex -mx-6”>
<div class=”w-1/2 px-6”>
<div class=”text-gray-700 font-bold text-sm mb-2”>To:</div>
<div v-for=”line in to”>{ line }</div>
</div>
<div class=”w-1/2 px-6”>
<div class=”text-gray-700 font-bold text-sm mb-2”>From:</div>
<div v-for=”line in from”>{ line }</div>
</div>
</div>
<table class=”w-full mt-8”>
<thead>
<tr>
<th class=”px-4 py-4 border-b text-right”>Quantity</th>
<th class=”px-4 py-4 border-b text-left”>Description</th>
<th class=”px-4 py-4 border-b text-right”>Price</th>
<th class=”px-4 py-4 border-b text-right”>Total</th>
</tr>
</thead>
<tbody>
<tr v-for=”[quantity, description, price] in items”>
<td class=”px-4 py-4 border-b text-right”>{ quantity }</td>
<td class=”px-4 py-4 border-b text-left”>{ description }</td>
<td class=”px-4 py-4 border-b text-right”>{ price | price }</td>
<td class=”px-4 py-4 border-b text-right”>{ price * quantity | price }</td>
</tr>
<tr>
<td class=”border-b”></td>
<td class=”border-b”></td>
<td class=”border-b px-4 py-4 text-right font-bold”>Subtotal</td>
<td class=”border-b px-4 py-4 text-right font-bold”>{ totalWithoutTaxes | price }</td>
</tr>
<tr>
<td class=”border-b”></td>
<td class=”border-b”></td>
<td class=”border-b px-4 py-4 text-right font-bold”>Taxes</td>
<td class=”border-b px-4 py-4 text-right font-bold”>{ taxes | price }</td>
</tr>
<tr>
<td class=”border-b”></td>
<td class=”border-b”></td>
<td class=”border-b px-4 py-4 text-right font-bold”>Total</td>
<td class=”border-b px-4 py-4 text-right font-bold”>{ total | price }</td>
</tr>
</tbody>
</table>
<div class=”mt-8 text-center text-gray-700”>
All prices in USD.
</div>
</div>
</div>
</div>
`,
el: ‘#app’,
computed: {
totalWithoutTaxes() {
return this.items.reduce((total, [quantity, _, price]) => {
return total + (quantity * price)
}, 0)
},
taxes() {
return this.totalWithoutTaxes * (1 + this.taxRate) - this.totalWithoutTaxes
},
total() {
return this.totalWithoutTaxes + this.taxes
},
},
filters: {
price: function (value) {
return `$${value.toFixed(2)}`
}
}
})

Here is the CodePen

Solution :

After you JSON fetch request, you need to convert the object to make it reactive as vue.js cannot detect property addition or deletion. You can use the $set on the instance make it reative.

created: function () {
fetch(‘data/invoicedetails.json’)
.then(resp => resp.json())
.then(items => {
//this.items = items
this.$set(this, ‘items’, items);
})
}

The vue.js documentation mentions this in Change Detection Caveats

[Vue.js] set value to <li> tag and update the prop on click $event vue.js

when trying to update props child to parent with on:click $event.

I passed the data and $event to parent to child, like below.
in parent;

<v-filter
:sortTypePrice=”sortTypePrice”
:sortTypeNewest=”sortTypeNewest”
v-on:updatePrice=”sortTypePrice = $event”
v-on:updateDate=”sortTypeNewest = $event”
/>

data(){
return {
sortTypePrice: “”,
sortTypeNewest: “”,
}
}

computed: {
filterArticles(){

let filteredStates = this.api.filter((article) => {
return (this.keyword.length === 0 || article.address.includes(this.keyword))
});

if(this.sortTypePrice == “price”) {
filteredStates = filteredStates.sort((prev, curr) => prev.price1 - curr.price1);
}
if(this.sortTypeNewest == ‘created_at’) {
filteredStates = filteredStates.sort((prev, curr) => Date.parse(curr.created_at) - Date.parse(prev.created_at));
}

return filteredStates;
},
}

I got the props and set the $event update. But my @click is not working.

in child

<ul>
<li v-model=”sortPrice” @click=”updatePrice” :value=”price”>lowest</li>
<li v-model=”sortDate” @click=”updateDate” :value=”created_at”>newest</li>
</ul>

props:[“sortTypePrice”, “sortTypeNewest”],
name: “controller”,
data(){
return {
price: “price”,
created_at: “created_at”,
sortPrice:this.sortTypePrice,
sortDate:this.sortTypeNewest,
};
},
methods: {
updatePrice(e){
this.$emit(“updatePrice”, e.target.value)
},
updateDate(e){
this.$emit(“updateDate”, e.target.value)
}
}

I think, when using very wrong way to do this. if it so, what is the right way to achieve this?

Solution :

You should not set both :value and v-model. You can try

<ul>
<li @click=”$emit(‘updatePrice’, ‘price’)” :value=”price”>lowest</li>
<li @click=”$emit(‘updateDate’, ‘created_at’)” :value=”created_at”>newest</li>
</ul>

Solution 2:

I find the following the best way to sync a prop between parent and child component:

in parent:

<!– notice `sync` modifier –>
<child :foo.sync=”val” />

in child:

<input v-model=”foo_“ />

props: [‘foo’],
computed: {

// create a local proxy for the `foo` prop
foo_{
// its value should be the value of the prop
get(){
return this.foo
},

// when we try to change it we should update the prop instead
set(val){
this.$emit(‘update:foo’, val)
}
}
}

Now in the child component you can work with the foo_ prop the same way as you would with the foo prop. Whenever you try to change it, it will update the foo prop in the parent and then sync down so that foo_ remains equal to foo. For example this.foo_ = 1 would make foo == 1.

This is the same pattern that is applied with the v-model directive. Check .sync Modifier for better understanding.