Accessing data variables in Vue method for a loop - vue.js

I want to access the data() variables
data () {
return {
name: '',
manufacturerIds: null,
supplierIds: null,
categoryIds: null,
productIds: null,
minPrice: 100,
maxPrice: 0,
priority: 0,
enable: true,
active: true,
minMargin: 0,
position: 0,
isLoading: false,
suppliers: [],
categories: [],
manufacturers: []
}
},
in a method in the same component. I know we can call it individually as property this.someVariable but what I want is to loop over all the variables to reset its values. So instead of calling them all one by one, I was thinking to loop over the data() and then assign it a null value (to reset).
I already tried this.data and this.getData() and this.data() but neither of them works.

It's a bad idea to reset the properties one by one because you will need to check each one of them to determine what value you need to set it to (null, array, boolean, etc). Do you really want to have if checks for all the properties?
A better way is to just clone the object before you make any changes to it and then just reset all the properties at once:
Method 1: store reset data locally
data () {
return {
// Add a property for storing unchanged data
defaultData: {},
data: {}
name: '',
manufacturerIds: null,
supplierIds: null,
categoryIds: null,
productIds: null,
minPrice: 100,
maxPrice: 0,
priority: 0,
enable: true,
active: true,
minMargin: 0,
position: 0,
isLoading: false,
suppliers: [],
categories: [],
manufacturers: []
}
},
created: {
// Clone data before you make any changes
this.cloneData()
},
methods: {
cloneData () {
// Method 1 (better way, but requires lodash module)
const clonedData = lodash.cloneDeep(this.$data)
// Method 2 (bad choice for complex objects, google "deep clone JS" to learn why)
const clonedData = JSON.parse(JSON.stringify(this.$data))
// Store the cloned data
this.defaultData = clonedData
},
resetData () {
// Reset the values using cloned data
this.$data = this.defaultData
}
}
Method 2: store reset data in Vuex store
data () {
return {
name: '',
manufacturerIds: null,
supplierIds: null,
categoryIds: null,
productIds: null,
minPrice: 100,
maxPrice: 0,
priority: 0,
enable: true,
active: true,
minMargin: 0,
position: 0,
isLoading: false,
suppliers: [],
categories: [],
manufacturers: []
}
},
created: {
// Clone data before you make any changes
this.cloneData()
},
methods: {
cloneData () {
// Method 1 (better way, but requires lodash module)
const clonedData = lodash.cloneDeep(this.$data)
// Method 2 (bad choice for complex objects, google "deep clone JS" to learn why)
const clonedData = JSON.parse(JSON.stringify(this.$data))
// Set the cloned data object to Vuex store
this.$store.commit('SET_DEFAULT_DATA ', clonedData)
},
resetData () {
// Reset the values using cloned data
this.$data = this.$store.state.defaultData
}
}
store.js
state: {
defaultData: {}
},
mutations: {
SET_DEFAULT_DATA (state, value) {
state.defaultData = value
}
}

What if you made an array of all the proporties in the data-method?
Example:
data() {
name: '',
manufacturerIds: null,
supplierIds: null
dataArray: [name, manufacturerIds, supplierIds]
}
and then call a method which loops over dataArray?

Related

How to implement dexie.js in Vue Chrome extension mv3

I have this code in my vue powered chrome extension
import dexie from 'dexie'
export default {
name: 'NewTab',
setup(){
return {
db: new dexie('storeManager', { autoOpen: true })
}
},
data() {
return {
sizes: [
'XS',
'S',
'M',
'L',
'XL',
'XXL',
'XXXL'
],
itemName: null,
itemPrice: null,
selectedSize: null,
savedItems: [],
pz: null,
}
},
mounted() {
},
methods: {
addItem(){
//db.version(1).stores({
// atricoli: "++id, name, size, color, pz, price"
//});
console.log(db)
console.log(this.itemName, this.selectedSize, this.pz)
this.savedItems.push({
name: this.name,
size: this.selectedSize,
pz: this.pz
})
}
}
}
I want to use dexie.js as database to store the input that the user will enter in the form I have in my new tab page. I've added the autoOpen option, to load the db but I'm not sure how to setup the table I need. Is correct to call the stores method every time the addItem is called?

Add object to array in nested json object - Redux

I'm getting a hard time adding an object to an array inside a JSON object.
This is my state:
const DATA =
{
data: [
{
id: 1,
routeName: 'my 2 route',
origin: 'Tel Aviv',
destination: 'Netanya',
date: '25-01-2021',
km: '60',
stops: [
{
id: 0,
address: 'test',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
},
{
id: 1,
address: 'adddress',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
}
],
},
{
id: 2,
routeName: 'my second route',
origin: 'Holon',
destination: 'Hadera',
date: '12-02-2021',
km: '70',
stops: [
{
id: 0,
address: 'address0',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer0',
tel: '00000000',
},
{
id: 1,
address: 'address1',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer1',
tel: '00000000',
},
],
},
],
}
I don't know how to write the reducer, tried few ways but the state doesn't change.
My reducer gets the route id + stop to add this route.
I will be happy for some help here :)
You'll need to find the parent route using the route's id, and then you'll need to create a new stops array by spreading, and adding the new stop.
You can use Array.findIndex() to find the actual route, and the slice the array, and update the route. However, another simple option is to map the data's routes, and update the route with the matching id.
const routeReducer = (state, { type, payload: { routeId, stop } }) => {
switch (type) {
case 'ADD_STOP':
return {
...state,
data: state.data.map(route => route.id === routeId ? {
...route,
stops: [...route.stops, stop]
} : route)
}
}
}
Usually in redux it's better to normalize the state, which makes it easier to update single items.
You could have a reducer that did something like this:
const updateItemInArray = (array, itemId, updateItemCallback) => {
return array.map(item => {
if (item.id !== itemId) return item;
// Use the provided callback to create an updated item
return updateItemCallback(item);
});
};
const data = (state = [], action) => {
switch (action.type) {
case 'ADD_STOP_SUCCESS':
return updateItemInArray(state, action.payload.routeId, (item) => ({...item, stops: [...item.stops, action.payload.stop]}))
default: return state;
}
}
When the action.type 'ADD_STOP_SUCCESS' is called the payload of the action would contain the new stop object you are wanting to add to the state.

Dynamically changing state vue

For my application I am using Vue-router and store to work together. In my state I am storing a few questions. The content of the questions is saved in my Store like so:
export default new Vuex.Store({
state: {
blabla: [
{
question: 'question1',
answer: false,
givenAnswer: null,
disabled: false,
},
{
question: 'question2',
answer: false,
givenAnswer: null,
disabled: false
}
],
score: null
},
getters: {
getQuestionList: state => {
return state.questions;
}
})
And of course with othe config, but this all works fine. I am getting this data through a Getter in my Vue template by using this code in my Component:
export default {
data() {
return {
questionId: this.$route.params.id - 1
}
},
computed: {
getQuestions () {
return this.$store.getters.getQuestionList
}
}
}
<p>{{ getQuestions[questionId].question }}</p>
Now I want to dynamically mutate the state of every question to disabled:false whenever someone answers the question in order to enable answering the next question. However I can not figure out how to exactly do it.
Can someone put me in the right direction? Thanks!
Edit for clarification: There is a list of 10 questions and when you start, only the first one is enabled at the start. When you answer question 1, question 2 should be enabled (question one also stays enabled), when you answer question 2, question 3 should be enabled, etc.
You can just commit a mutation that sets disabled: false for the specified element:
Cmponent
<button #click="submitQuestion(question.id)"></button>
methods: {
submitQuestion (id) {
// ...
this.$store.commit('ENABLE_QUESTION', id + 1) // passing id of the next question
}
}
Store
state: {
questions: [
{
id: 0,
question: 'question1',
answer: false,
givenAnswer: null,
disabled: false,
},
{
id: 1,
question: 'question2',
answer: false,
givenAnswer: null,
disabled: false
}
]
}
...
mutations: {
ENABLE_QUESTION (state, id) {
let questionIndex = state.questions.findIndex(item => item.id === id)
state.questions[questionIndex].disabled = false
}
}
in your store put this mutation code :
mutations: {
enable (state) {
state.questions.forEach(item => {
item.disabled = false
)}
}
}
and in your component you can commit this mutation easily as follows:
this.$store.commit('enable')

Error in data(): "TypeError: this.game.league_person_result[0] is undefined"

Wanted to do if rendering data properties in vuejs2
I have tried to put into data or computed properties, but it doesn't work.
data() {
return {
edit: false,
leagueGameResult: {
person_id: this.game.person.id,
person_result: this.game.person_result,
opponent_id: this.game.opponent.id,
opponent_result: this.game.opponent_result,
game_id: this.game.id,
league_id: this.$route.params.id,
},
leagueGameResultEdit: {
person_id: this.game.person.id,
person_result: this.game.person_result,
person_result_id: this.game.league_person_result[0].id ? this.game.league_person_result[0].id : null,
opponent_id: this.game.opponent.id,
opponent_result: this.game.opponent_result,
opponent_result_id: this.game.league_person_result[1].id ? this.game.league_person_result[1].id : null,
game_id: this.game.id,
league_id: this.$route.params.id,
},
}
},
I want data, that if not exist it would still working, because now its stack, when data is not provided.
So the error suggests that this.game.league_person_result[0] is undefined, which means you can't access its id property. It should be sufficient just to check whether that object is present before trying to grab the id.
data() {
const game = this.game
const leagueId = this.$route.params.id
const [league0, league1] = game.league_person_result
return {
edit: false,
leagueGameResult: {
person_id: game.person.id,
person_result: game.person_result,
opponent_id: game.opponent.id,
opponent_result: game.opponent_result,
game_id: game.id,
league_id: leagueId
},
leagueGameResultEdit: {
person_id: game.person.id,
person_result: game.person_result,
person_result_id: (league0 && league0.id) || null,
opponent_id: game.opponent.id,
opponent_result: game.opponent_result,
opponent_result_id: (league1 && league1.id) || null,
game_id: game.id,
league_id: leagueId
},
}
},
I've tried to reduce the duplication a little but there's a lot more that can be done given leagueGameResult and leagueGameResultEdit are almost the same.
I would also suggest trying to move the league_id out to a prop rather than grabbing it via this.$route. Vue Router allows you to inject route parameters as props.

How to store multiple api's data with VueX and add properties to the response

Suppose i want to store data from multile Api requests - when the App is instantiated,
and i also want to add properties to each response
Here is the url of the api 'http://api.open-notify.org/iss-pass.json?lat=LAT&lon=LON'
Updated
I want to instantiated the app with all the data from a couple of get requests - so i'm looping all the requests - that part is works fine , but i also want to be able to add to response.data.response object properties from the cities array, so the finale result will be :
cities: [{
id: 0,
cityName: 'Select a city',
stuff from response.data...
},......
Here is the main part of the Api call
const store = new Vuex.Store({
state: {
satelliteData: [],
dataObj:[],
loading: true,
cities: [{
id: 0,
cityName: 'Select a city',
cityLocation: null
},
{
id: 1,
cityName: 'Tel Aviv',
cityLat: '32.0853',
cityLon: '34.7818'
},
{
id: 2,
cityName: 'London',
cityLat: '51.5074',
cityLon: '-0.1278'
},
{
id: 3,
cityName: 'New York',
cityLat: '40.7128',
cityLon: '-74.0060'
},
],
},
actions: {
loadData({commit}) {
for(var i=0; i<this.state.cities.length; i++){
var currData = this.state.cities[i];
if(!!this.state.cities[i].hasOwnProperty('cityLat'))
axios.get(URL, {
params: {
lat: this.state.cities[i].cityLat,
lon: this.state.cities[i].cityLon,
},
}).then((response) => {
Here is where i want to be able to access the Cities array
/* var cities = this.$store.state.cities;
console.log(cities) */
commit('updateSatelliteData', response.data.response)
commit('changeLoadingState', false)
})
}
}
},
Fiddle
Since i'm new to Vue - i'm sure that there are a couple of mistakes here. Thanks