how to keep calculating each time the page is refreshed - javascript

I cannot assign the value of the calculated user data to the object in the data, but the data is lost when the page is refreshed.
import Vuetify from "vuetify"
import {
UserData
} from "../../store/userModule";
import jsonDict from "../../jsonFiles/data.json"
import jsonfile from "../../jsonFiles/jsonfile";
export default {
name: "userProfileUpdate",
data() {
return {
selected: "Choose Province",
rules: [
value => !!value || 'Bu alan boş bırakılamaz',
value => (value || '').length <= 20 || 'Max 20 characters',
value => {
const pattern = /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return pattern.test(value) || 'Geçersiz e posta'
},
],
options: jsonDict.Gender,
options2: jsonDict.educational_status,
educational_status: '',
gender: '',
birthday: '',
email: '',
phone_number: '',
username: '',
first_name: '',
last_name: '',
profileData: {
}
}
},
created() {
this.$store.dispatch('initUserData')
this.$store.dispatch('inijson')
},
I have tried many ways it disappears when the page is refreshed even creating computed data but somehow it could not keep the data on the screen after the page refresh
computed: {
genderq() {
for (var i in this.$store.getters.user) {
return this.$store.getters.user[i]
}
return this.$store.getters.user
},
userdata() {
for (const i in this.$store.getters.getUser) {
var data = this.$store.getters.getUser[i]
this.username = data['username']
//this.$store.dispatch('getJsonData',data['gender'])
return data
}
return this.$store.getters.getUser
},
},

Hey you could try using localStorage or sessionStorage, and add the mounted() property to your component (this property is fired when the component is mounted) and then you could affect your data() values from the localStorage for example
data() => { myData: 0 },
computed()=>{
storeValue(){
localStorage.setItem('data', this.myData)
}
},
mounted() =>{
localStorage.getItem('data') ? this.myData = localStorage.getItem('data') : null //null because in data() myData has a default value but you can say this.myData = 0
}
With the mounted lifecycle property and the browser storage, you will have a trace of every value you want to keep between 2 refreshes (look for both localstorage and sessionStorage as they don't last the same time), basically, you can have a method (not a computed) that stores the object you want in the storage, then you can call this method at the end of every computed property that modifies the data you want to keep between refreshes.
edit: here is a link to help you to understand the lifecycle of a vue component it might help you later too if you want to create more complex components, lifecycle diagram
Best regards

Related

Is there a way to shorten defining v-model data, Vue.js and Laravel

On my edit page of CRUD project, I have a code that fills the form with values of which record is being edited. I use v-model to define HTML inputs, but the code seems too long.
I get the data from the prop, and fill the v-model.
My code that fills v-model
created() {
this.studentData = this.student;
this.first_name = this.student.first_name;
this.last_name = this.student.last_name;
this.student_number = this.student.last_name;
this.phone_number = this.student.phone_number;
this.email = this.student.email;
this.birth_date = moment(this.student.birth_date).format('YYYY-MM-DD');
this.school_name = this.student.school_name;
}
The way I get the data using prop: props: ['student'] and in blade <student-edit-component :student="{{$student}}">
Defining v-models in script
data () {
return {
first_name: '',
last_name: '',
student_number: '',
phone_number: '',
email: '',
birth_date: '',
school_name: '',
};
},
That fills the value on the form inputs with it's data.
Is there a way to shorten this code using props or arrays?
Please help me, I'm so new to Vue
You can change your model of data adding a new layer. For example:
data() {
return {
currentStudent: {
first_name: '',
last_name: '',
student_number: '',
phone_number: '',
email: '',
birth_date: '',
school_name: '',
}
}
},
Then in created you can use simple
created() {
this.currentStudent = this.student;
this.currentStudent.birth_date = moment(this.student.birth_date).format('YYYY-MM-DD');
},
And in all component replace names by names with currentStudne eg in v-models:
first_name -> currentStudne.first_name
You can also read about Vue.$set
https://v2.vuejs.org/v2/guide/reactivity.html
You can use the object studentData, it is working well with v-model.
First, you pass the props like that :
<student-edit-component :student="student"> (no need to use the ${{}}).
Then in the component `StudentEditComponent', you can use :
props: {
student: {
type: Object,
required: true,
default : () => {},
}
}
You should use the type, required and default properties, it is a good practice.
Then
data () {
return {
studentForm: {},
};
},
created() {
this.studentForm = this.student;
}
In the template, you can after that use v-model="studentForm.first_name"

Input not updated when incrementing with button on VueJS

I have two components called OrderComponent and ModalOrder (with vue-modal-js)
I passed the data from OrderComponent to ModalOrder, and in ModalOrder, I use an input tag to contain quantity_ordered and button to increment its value like this
<!-- ModalOrder.vue -->
<input v-model="order.quantity_ordered" />
<button #click.prevent="increment"></button>
in my script tag
// ModalOrder.vue
<script>
export default {
name: "ModalOrder",
methods: {
beforeOpen (event) {
// if there's a data passed from the OrderComponent, I put it to "order" data
this.order = event.params
// if there's no data passed a.k.a a new record, I have to set the default value to 0
if (this.order.quantity_ordered == undefined) {
this.order.quantity_ordered = 0
}
},
...
increment() {
this.order.quantity_ordered += 1
// this method will not increment the input UI, if it's a new record
},
},
data() {
return {
order : {
code: '',
table_name: '',
customer_name: '',
employee_name: '',
menu_name: '',
quantity_ordered: ''
},
}
}
}
</script>
My problem is whenever I want to make a new order data, then when I click the button to increment, the input value UI isn't incrementing
Thank you in advance.
You're falling prey to one of Vue's change detection caveats...
Vue cannot detect property addition or deletion
So for your new records, you would need to either set the property when you assign the new value to order
this.order = {
quantity_ordered: 0,
...event.params // if "quantity_ordered" is set here, it will override the default.
}
or dynamically set it after
if (this.order.quantity_ordered == undefined) {
this.$set(this.order, 'quantity_ordered', 0)
}
As mentioned in the comments, you should also default your data property to 0 if it's meant to be numeric
data: () => ({
code: '',
table_name: '',
customer_name: '',
employee_name: '',
menu_name: '',
quantity_ordered: 0 // 👈
})

Vuex Getters doesn't call state

I trying to return back sorted data (which is the already defined state) in a list with the help of a getter, then assign it to the html list in my vue, but it seems it's empty when I check with the vuex tools.
I don't know what am doing wrong.
Below is my store.js file
export default {
namespaced: true,
state:{
displayChatMessages: [],
},
mutations:{
create(state, payload) {
state.displayChatMessages.push(payload)
},
reset(state){
state.displayChatMessages = []
},
},
actions :{
getAllData:({commit}, payload) => {
commit('create',payload)
},
},
getters:{
filteredChatMessages: state => (chatID) => {
return state.displayChatMessages[0]
.filter(el => el.groupid === chatID).sort((l,r)=> l.timestamp - r.timestamp)
},
},
}
Then, after, I call it in the computed area like below :
...mapGetters('chatMessages',['filteredChatMessages']),
Then , I call the Getter inside my function , like below :
getFilteredMessages: function() {
let vm = this
return vm.filteredChatMessages(vm.groupID)
},
Then afterwards, then I set the getFilteredMessages() to the list , getFilteredMessages() , is also defined in the computed section.
But when I look into my vuex tools , I don't see it as an array :
What am I doing wrong ?

Update dynamic components disabled state based on Vuex state value

I have no idea if what I'm doing is correct or not, but here's a simplified version of what I'm trying to do:
I want to have 3 file inputs, with the 2nd and 3rd disabled until the 1st one has had a file selected.
I've tried to do is set the Vuex state variable to whatever the first file input is has selected, but upon doing that the other 2 inputs don't update their disabled state.
I have some file inputs that are created dynamically, like so:
Vue.component('file-input', {
props: ['items'],
template: `<div><input type="file" v-on:change="fileSelect(item)" v-bind:id="item.id" v-bind:disabled="disabledState"></div>`,
methods: {
fileSelect: function(item) {
store.commit('fileSelect', file);
}
},
computed: {
disabledState: function (item) {
return {
disabled: item.dependsOn && store.getters.getStateValue(item.dependsOn)
}
}
}
}
The data for the component is from the instance:
var vm = new Vue({
data: {
items: [
{ text: "One", id: "selectOne" },
{ text: "Two", id: "selectTwo", dependsOn: "fileOne" },
{ text: "Three", id: "selectThree", dependsOn: "fileOne" }
}
});
Now, notice the "dependsOn". In the Vuex store, I have a corresponding state item:
const store = new Vuex.Store({
state: {
files: [
{
fileOne: null
}
]
},
mutations: {
fileSelect(state, file) {
state.files.fileOne = file;
}
},
getters: {
getStateValue: (state) => (stateObject) => {
return state.files.findIndex(x => x[stateObject] === null) === 0 ? true : false;
}
}
});
Now, the above works when everything is first initialized. But once the first input has something selected, the other two inputs don't change.
I'm not sure how to update the bindings once a mutation of the state occurs.
I think you need to refactor your mutation to make the state property mutable, like this:
fileSelect(state, file) {
Vue.set(state.files[0].fileOne, file);
}
Well, I figured it out...
Because my state object is an array of objects, I can't just change one of the property's values with state.files.fileOne. I needed to do state.files[0].fileOne.

How do you run a function when any data in an object is changed using Vuejs?

So I have the following data, and my goal is to recalculate the user's results every time data in this object is changed. Here is the data.
data() {
return {
test: 0,
userData: {
sex: null,
age: null,
feet: null,
inches: null,
activity: null,
goal: null,
},
}
}
Now I have tried to implement both watch and computed, but it seams Vue is not noticing when individual items in the object are changed. However, if I take some data out of the object it does notice the change.
Here is what I tried for watch:
watch: {
userData: function () {
console.log("Changed");
}
}
The result was nothing in the console.
For computed I tried the following:
computed: {
results: function () {
console.log(this.userData);
return this.userData.sex;
}
}
But again nothing was printed in the console.
If I tried with the test variable:
watch: {
test: function () {
console.log("Changed");
}
}
It WOULD output changed when the variable was changed. So that works because it is not an object.
Any help would be very appreciated. Again the goal is to recalculate results whenever any userData is changed.
Here is one way to do it. You need (as #match mentioned) use Vue.set() or vm.$set(). I found it was also necessary to update your watcher property to userData.sex.
new Vue({
el: "#app",
data: {
status: '',
userData: {
sex: ''
},
},
methods: {
updateValues(){
// Or Vue.set()
this.$nextTick( function(){
const newUserData = Object.assign({}, this.userData);
newUserData.sex = "Male";
this.userData = newUserData;
});
}
},
watch: {
userData: function (v) {
this.status += "userData Changed";
},
'userData.sex': function (v) {
this.status += "\nuserData.sex Changed";
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<pre v-text="'userData.sex = ' + userData.sex"></pre>
<pre v-text="status"></pre>
<button #click="updateValues()">
Change Sex
</button>
</div>
EDIT:
Re-assigning the whole object, userData, triggers the watch.userData.
Are you actually using the results property (in your template for example)? Computed properties do not get recomputed if they are not being used.
As opposed to what #match says, I doubt you have a reactivity problem since you do not add or delete properties (they already exist in your data so they are already reactive).

Categories

Resources