Hi this is my code,
var vm = new Vue({
el: '#el',
data: {
input: {
sorting: "",
brand: null,
model: null,
country: "all",
cap: "",
radius: ""
}
},
watch: {
input: {
handler(newInput) {
},
deep: true
}
}
});
Here I'm watching weather input object changes. But I need to watch only some items only input object. For example I need to do something if input.country changes but not when input.brand changes. Unfortunately my code is complex and can't take items out of input object.
Just watch what you need:
watch: {
'input.country': {
handler(newCountry) {
}
}
}
Declare a computed value who target this.item.country:
computed: {
itemCountry() {
return this.item.country;
}
}
And watch this new computed value:
watch: {
itemCountry: {
immediate: true,
handler(newInput) {
// do your stuff
}
}
}
Related
I'm learning Vue JS and I am creating my components.
I'm stuck on an issue.
I would like to have my component taking in params an array of object like that :
data() {
return {
items: [
{
text: 'Admin',
href: '#'
},
{
text: 'Manage',
href: '#'
},
{
text: 'Library',
active: true
}
]
}
So, I tried to implement my component with props :
props: {
items: {
type: Array,
required: true
}
However, I have no idea how to say that : if items does not contains active key, then it should have a false default value.
If you have any advices/links or explanations, I will be very grateful to you.
You can make a computed property which will fill-in those active: false by default, and override it with the provided items:
props: {
items: {
type: Array,
required: true
}
},
computed: {
normalizedItems() {
return this.items.map(x => ({ active: false, ...x }));
}
}
You would then use normalizedItems in your template instead of items
I'm trying to make the code below work knowing that computed properties can't take parameters. Do you have any idea ? I'm exploring the use of watchers on functions but I was wondering if there was not an easier solution to do this.
var app = new Vue({
el: '#app',
data() {
return {
sessions: {
"156": {
tickets: {
"01": {
available: true,
},
"02": {
available: false,
},
}
},
},
tickets: {
"01": {
attr: "somestring",
},
"02": {
attr: "someotherstring",
},
},
},
};
},
computed: {
sessionTickets(session) {
let _this = this;
let sessionTickets = {};
$.each(_this.session.tickets, function(ticketId, sessionTicket) {
if(sessionTicket.available) {
sessionTickets[ticketId] = _this.tickets[ticketId];
}
});
return sessionTickets;
},
},
});
<div v-for="session in sessions">
<div v-for="sessionTicket in sessionTickets(session)">
{{ sessionTicket.attr }}
</div>
</div>
Thanks to "WallOp" for making me realize that my computed property is in a sessions loop and so it can normally become a class method and be refreshed on sessions refresh !
I think you can use computed property. Just filter tickets of sessions. Like this:
var app = new Vue({
el: '#app',
data() {
return {
sessions: {
"156": {
tickets: {
"01": {
available: true,
},
"02": {
available: false,
},
}
},
},
tickets: {
"01": {
attr: "somestring",
},
"02": {
attr: "someotherstring",
},
},
},
};
computed: {
filteredSessions() {
return this.sessions.map( session => {
let tickets = {};
for(key in session.tickets) {
if(session.tickets[key].available && this.tickets.hasOwnProperty(key)) {
tickets[key] = this.tickets[key];
}
}
session.tickets = tickets;
return session;
});
},
},
});
<div v-for="session in filteredSessions">
<div v-for="ticket in session.tickets">
{{ ticket.attr }}
</div>
</div>
I'm working on an autosave feature for a vue app that sends data to api every time a change is made to the vue app data. Is it possible to ignore certain properties of an objected when using a vue watch? The object has multiple values that I want to watch to auto save and only 1 or 2 that would be ignore so it doesn't seem to make sense to set up a watch function for all the properties I want but instead just ignore the 1 that I don't.
This is the basic structure of the data:
data:{
template: {
name: "Template",
id: 1,
variables: [
{
name: "v1",
color: "#fff",
group: 1,
isSelected: true
},
{
name: "v2",
color: "#fff",
group: 3,
isSelected: false
}
]
}
}
and the basic watch function:
watch: {
template: {
handler: function(){
this.save();
},
deep: true
}
}
The isSelected field for the variables in the template are used for UI purposed only and I would like the watch to ignore that field changing because they don't get saved. I don't want to have to set up a watch function for every field in variables but instead do something in the watch like:
ignore: "template.variables.isSelected"
You can't get old value for mutation object so I think creating some helper data as below temp(save old data) will help your problem .Then check old and new data ....
var app = new Vue({
el: "#app",
data:{
a: 1,
template: {
name: "Template",
id: 1,
variables: [
{
name: "v1",
color: "#fff",
group: 1,
isSelected: true
},
{
name: "v2",
color: "#fff",
group: 3,
isSelected: false
}
]
},
temp: {}
},
mounted: function() {
// this.template.variables[0].isSelected = false;
this.temp = JSON.parse(JSON.stringify(this.template));
this.$set(this.template.variables[0],"isSelected", 222);
},
watch : {
template: {
handler: function(changeVal) {
var flag = true;
for(var i in changeVal.variables) {
if(changeVal.variables[i].isSelected != this.temp.variables[i].isSelected) {
flag = false;
}
}
this.temp = JSON.parse(JSON.stringify(this.template)); // assign changed data as old data again for next process
if(flag) console.log("saveData");// this.save();
else console.log("notsave");
},
deep: true
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
I'm working on two vue component.sending parent component array data to child component using props.now i want to set pre-selected value in child component dropdownlist.
Here is my code sample:
props:{
// pre-selected value based on this.
userdata:{
type:[Array,Object],
required:true,
},
roles:{
type:[Array,Object],
required:true,
},
},
data(){
return{
mutableRoles:[],
}
},
and this is my view part:
//i want set pre-selected value on this dropdownlist
<select multiple v-model="mutableRoles" class="form-control">
<option v-for="(role,index) in roles" v-bind:value="role.id" >{{role.name}}</option>
</select>
I have seen many example where show only using string. but in my case both are array.
Try this:
const CurrentRole = Vue.component("current-role", {
template: `
<div>
<label>Options</label>
<select v-model="roleId" #change="changeValue">
<option v-for="v in roles" :key="v.id" :value="v.id">{{v.title}}</option>
</select>
</div>
`,
props: {
userdata: {
type: [Array, Object],
required: true,
},
roles: {
type: [Array, Object],
required: true,
}
},
data: _ => ({
roleId: null
}),
methods: {
changeValue() {
this.userdata.role = this.roles.find(e => e.id == this.roleId)
},
},
mounted() { // for initial state
this.roleId = this.userdata.role.id
},
watch: {
userdata(v) { // for changes on parent
if (v) this.roleId = v.role.id
}
}
})
new Vue({
el: "#app",
data: {
rlist: [{
id: 1,
title: "a"
}, {
id: 2,
title: "b"
}, {
id: 3,
title: "c"
}],
user: {
role: {
id: 3,
title: "c"
}
}
},
methods: {
changeUser() {
this.user = {
role: {
id: 1,
title: "a"
}
}
}
}
})
<script src="https://unpkg.com/vue#2.5.22/dist/vue.js"></script>
<div id="app">
<p>User: {{user}}</p>
<current-role :userdata="user" :roles="rlist">
</current-role/>
<button #click="changeUser">change user</button>
</div>
The select is tailored for primitive values, therefore you'll need to add helper functions.
Higher level vue frameworks such as vue-material, vuetify, element and muse-ui tend to offer components to cope with such problems with a higher abstraction level.
EDIT:
I changed the snippet in order to make it closer to your situation.
I have a Base Vue Component, which handles items. Now i've extended that component with a CompanyItem and a EducationItem. But when i load both the directives, it will call a GET method 4 times. Also: i have a click handler on 2 models (example: openUpdateOrCreateModal()) which is loaded in one of the directives. When i click, the other directive is triggered too. Anyone a idea?
Base
module.exports = {
props: ['user', 'update_url', 'store_url', 'delete_url', 'show_url', 'index_url', 'item_type'],
mounted() {
Bus.$emit('index');
},
data(){
return {
form: {},
items: [],
mainItem: {},
item: {},
}
},
created(){
},
methods: {
resetForm(){
this.form = new SparkForm({
general: {
title: null,
},
item: this.getItemProperties(),
address: {
address_line_1: null,
address_line_2: null,
city: null,
province: null,
zip_code: null
}
});
this.mainItem = null;
},
getItemProperties(){
return {};
},
showModal(){
$('#create-update-'+this.item_type+'-modal').modal('show');
},
hideModal(){
$('#create-update-'+this.item_type+'-modal').modal('hide');
},
/**
* Gets a list with specific items
*/
index(){
console.log('Call index');
axios.get(this.index_url)
.then(response =>
{
this.items = response.data.data;
});
},
}
};
Education
var base = require('./cv-item-base');
Vue.component('cv-educations-management', {
mixins: [base],
methods: {
getItemProperties(){
return {
start_at: null,
end_at: null,
description: null,
finished_education: null,
level: null,
}
}
}
});
Companies
var base = require('./cv-item-base');
Vue.component('cv-company-list', {
mixins: [base],
methods: {
getItemProperties(){
return {
start_at: null,
end_at: null,
position: null,
description: null,
phone_number: null,
branch: null,
referral: null,
}
}
}
});
HTML
<cv-company-management :user="user"
:update_url="'{{route('application.manage.companies.update')}}'"
:show_url="'{{route('application.manage.companies.show')}}'"
:delete_url="'{{route('application.manage.companies.destroy')}}'"
:store_url="'{{route('application.manage.companies.store')}}'"
:index_url="'{{route('application.manage.companies.index')}}'"
:item_type="'company'"
inline-template>
</cv-company-management>
<cv-education-management :user="user"
:update_url="'{{route('application.manage.educations.update')}}'"
:show_url="'{{route('application.manage.educations.show')}}'"
:delete_url="'{{route('application.manage.educations.destroy')}}'"
:store_url="'{{route('application.manage.educations.store')}}'"
:index_url="'{{route('application.manage.educations.index')}}'"
:item_type="'education'"
inline-template>
</cv-education-management>