I got data from API using computed. "UserModule.userInfo.usrEmail" is the state in my vuex. Like below:
data() {
return {
vModel: {
email: {
value: "",
},
}
}
}
computed: {
email:{
get: function(){
return UserModule.userInfo ? UserModule.userInfo.usrEmail : "";
},
set : function(email){
this.vModel.email.value = email
}
},
}
And then show it to user like below:
<input v-model="email"></input>
User can edit email and also cancel their edit process and return to their previous data but in edit everything was correct but when i want to cancel this process my previous data did not show in the input and i saw my new data which is not correct i want to cancel it. This is my cancel method on input:
resetInput(input) {
this.vModel.email.value = this.email
},
"this.email" refer to my computed which is get data from API.
How can i write this cancel process correctly and see my previous data in input tag?
so you can use this solution:
data() {
return {
useGet :{
email: true,
},
}
}
in your method:
resetInput(input) {
this.useGet.email = true
},
and in your computed:
email: {
get: function () {
if (this.useGet.email) {
return UserModule.userInfo ? UserModule.userInfo.usrEmail : ""
}
return ""
},
set: function (email) {
this.useGet.email = false
}
},
this is because of your UserModule.userInfo.usrEmail.
this state does not update.
your get in computed will be work when your UserModule.userInfo.usrEmail changes.
Related
I just need some help identifying what I am missing here. Just can't seem to send the correct data through:
Parent with the CommunicationPreference component:
<CommunicationPreference
v-for="(communication, index) in communicationPreference"
:key="index"
:consent="communication.consent"
:name="communication.name"
#update="updateConsent(consent)"
/>
METHOD
methods: {
async updateConsent(consent) {
await this.$store.dispatch('account/updateCommunicationPreferences', { consent })
},
},
CommunicationPrefernce.vue
<Button
class="mr-4"
:text="YES"
:type="consent === true ? 'primary' : 'secondary'"
#clicked="updateConsent(true)"
/>
<Button
:text="NO"
:type="consent !== true ? 'primary' : 'secondary'"
#clicked="updateConsent(false)"
/>
PROPS:
props: {
type: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
consent: {
type: Boolean,
default: true,
},
},
METHOD:
updateConsent(consent) {
this.$emit('update', consent)
},
STORE:
async updateCommunicationPreferences({ commit, state }, payload) {
const { consent } = payload
const { communicationTypeName } = state.communicationTypeName
try {
const response = await this.$axios.put(`/communication-consent/${communicationTypeName}`, consent)
const { data: updatedCommunicationPreferences } = response.data
commit('SET_UPDATED_COMMUNICATION_PREFERENCES', updatedCommunicationPreferences)
} catch (error) {
commit('ADD_ERROR', { id: 'updateCommunicationPreferences', error }, { root: true })
}
},
Attached is the UI I am working towards for reference. the idea is each time the user selects either YES or NO the selection is updated and reflected on the UI
Here is my Swagger doc:
I assume that you have a mapped getter for communicationPreference prop, so that this is correct.
I also assume that your #clicked event prop is proper provided the implementation of Button.vue.
So try to change #update="updateConsent(consent)" to #update="updateConsent"
Right now it seems to me that you are making a small mistake between a function call and declaration. Having it such as #update="updateConsent" will trigger updateConsent method, and the function declaration:
async updateConsent(consent) {
await this.$store.dispatch('account/updateCommunicationPreferences', { consent })
},
will take care of getting the consent you pass in your event trigger.
I am trying to setup a button that changes a data value in Vue but also have it set using localStorage initally. This way I can have it keep the previous state it was in before a page refresh. Below is the code I'm using and I'm able to get it to work but know that it would be preferable to use the computed section but haven't been able to get that to work properly.
Would anyone know what is going wrong?
My button is triggered using the testing method and the variable in question is isGrid.
export default {
data() {
return {
option: 'default',
}
},
components: {
FileUploader,
},
mixins: [
visibilitiesMixin,
settingsMixin
],
props: {
vehicleId: {
type: Number,
required: true,
default: null,
}
},
computed: {
...mapState([
'isLoading',
'images',
'fallbackImageChecks',
'selectedImages'
]),
isGrid: {
get() {
return localStorage.getItem('isGrid');
},
},
imagesVModel: {
get() {
return this.images;
},
set(images) {
this.setImages(images);
}
},
selectedImagesVModel: {
get() {
return this.selectedImages;
},
set(images) {
this.setSelectedImages(images);
}
},
removeBgEnabled() {
return this.setting('nexus_integration_removebg_enabled') === 'enabled';
},
},
mounted() {
this.loadImages(this.vehicleId);
},
methods: {
testing() {
if (this.isGrid === 'false' || this.isGrid === false) {
localStorage.setItem('isGrid', true);
this.isGrid = true;
console.log(this.isGrid);
console.log(localStorage.getItem('isGrid'));
} else {
localStorage.setItem('isGrid', false);
this.isGrid = false;
console.log('b');
console.log(this.isGrid);
console.log(localStorage.getItem('isGrid'));
}
},
}
I suggest you use vuex with vuex-persistedstate.
https://www.npmjs.com/package/vuex-persistedstate
I have this code in my Vue.js component:
mounted() {
if (localStorage.dobDate) {
this.form.dobDate = localStorage.dobDate;
}
if (localStorage.dobMonth) {
this.form.dobMonth = localStorage.dobMonth;
}
if (localStorage.dobYear) {
this.form.dobYear = localStorage.dobYear;
}
},
watch: {
"form.dobDate": {
handler: function(after, before) {
localStorage.dobDate = after;
},
deep: true
},
"form.dobMonth": {
handler: function(after, before) {
localStorage.dobMonth = after;
},
deep: true
},
"form.dobYear": {
handler: function(after, before) {
localStorage.dobYear = after;
},
deep: true
}
Ask you can see it can get very repetitive, if for example I had a large form, and I don't want to do this for every field. Is there a way I can approach this to make it more DRY? Is there a way I can make it more dynamic for any field in a form for example?
In the mounted hook create an array of localStorage fields ["dobDate","dobMonth","dobYear"] and loop through it using forEach method, for each field localStorage[fieldName] check if it's defined using conditional operator, if it's defined assign it to the correspondant field name in the form data property else pass to the next element:
mounted(){
["dobDate","dobMonth","dobYear"].forEach(field=>{
localStorage[field]?this.form[field]=localStorage[field]:{};
})
}
In the watch property watch the form object deeply (watch its nested fields) then loop through its keys by doing the reciprocal operation made in mounted hook :
watch: {
form: {
handler: function(after, before) {
Object.keys(after).forEach(key=>{
localStorage[key]=after[key]
})
},
deep: true
}
}
Here is another approach with multiple (no deep) watchers.
data: {
form: {},
dateFields: ['dobDate', 'dobMonth', 'dobYear']
},
mounted() {
for (const dateField of this.dateFields) {
if (localStorage[dateField])
this.$set(this.form, dateField, localStorage[dateField])
}
},
created() {
for (const dateField of this.dateFields) {
this.$watch('form.' + dateField, function(after, before) {
localStorage[dateField] = after;
});
}
}
I ignore if it's more or less efficient than only one deep watcher. It may depends on the way your data change.
I'm sure you must have reasons for using localStorage for saving form data in localStorage, so with this code, you can pass the whole form object to localStorage and can retrieve that. in this case, any change in form would make this watch run
mounted() {
if (localStorage.form) {
this.form = localStorage.form
}
},
watch: {
"form": {
handler: function(after, before) {
localStorage.form = after;
},
deep: true
}
}
so i am trying to figure out whether this is possible, i am using a prop to dynamically name a field in data. So essentially i want to add a watcher to the dynamically added data field. Is this possible?
export default {
props: {
type: {
type: String,
required: true
}
},
data() {
return {
[this.type]: {
place_type: "house"
}
}
},
watch: {
"[this.type].place_type": function(val) {
console.log(val);
}
}
}
Here is my attempt, but it does not work with that syntax. Any ideas? Thanks
I have an object like this:
users: {
email: '',
password: ''
}
When user edits something, I want to detect the changes made in the key of the users object & save that key in another object(say editedFields)! How can I do this?
I tried using deep watchers like this:
watch: {
users: {
handler: function(val, oldVal) {
//
},
deep: true
}
}
But I am not sure how to get that edited key! Please help
I think this works:
watch: {
'users.email': function(newEmail, oldEmail) {
//
}
}
I think something like this might work?
data: function() {
return {
user: {
email: '',
password: ''
},
editedFields: []
}
},
watch: {
users: {
handler: function(val, oldVal) {
for (var key in val) {
if(val[key] != oldVal[key]) {
this.data.editedFields.push(key);
}
}
},
deep: true
}
}
But actually, there better way of handling this would be to create a new Vue component for each field. You can then test to see if its been updated in each component.