How do I use JSON data with vuex store (no webpack) - vue.js

I managed to setup my first vuex store successfully.
An array of data is passed from the store to the desired component and rendered correctly.
Now I'd like to get my data from a JSON file, but cant get it to work.
I am not making use of a webpack, because sometimes I need to work on my project in an environment where these tools are not available.
The following, without retrieving data from a JSON file is working:
STORE.JS
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
products: [
{ name: "Avocado Zwem Ring", inventory: 47, unit_price: 77, image:"a.jpg", new:true },
{ name: "Danser Skydancer", inventory: 5, unit_price: 45.99, image:"a.jpg", new:true}
]
},
});
SHOP.VUE
<template>
<comp-products v-bind:products="products"></comp-products>
</template>
<script>
module.exports = {
components: {
'comp-products': httpVueLoader('components/comp-products.vue')
},
computed:{
products(){
return this.$store.state.products
}
}
}
</script>
I have tried the following but it does not render anything but also does not return an error.
STORE.JS
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
products: [],
},
mounted() {
axios
.get("json/products.json")
.then(response => {
this.products = response.data.products;
})
},
});
SHOP.VUE
<template>
<comp-products v-bind:products="products"></comp-products>
</template>
<script>
module.exports = {
components: {
'comp-products': httpVueLoader('components/comp-products.vue')
},
computed:{
products(){
return this.$store.state.products
}
}
}
</script>
products.json
{
"products":[
{
"sku":"1",
"name": "Danser Skydancer",
"inventory": 5,
"unit_price": 45.99,
"image":"a.jpg",
"new":true
},
{
"sku":"2",
"name": "Avocado Zwem Ring",
"inventory": 10,
"unit_price": 123.75,
"image":"b.jpg",
"new":false
}]
}
I am sure that the path to the json file and the setup of axios is correct because I managed to retrieve and render the json data without making use of the vuex store.

For setting variables in the store you should use mutations.
After setting up the store call your api and then call the mutation on the store with the resulted data.
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
products: [],
},
mutations: { //Mutations are like setters
SET_PRODUCTS: (state, products) => { //capitalization is good-practice for vuex-mutations
state.products = products;
}
}
});
const setProductToStore = () => {
axios
.get("json/products.json")
.then(response => {
store.commit('SET_PRODUCTS', response.data.products);
})
}
setProductToStore();
Something like this should work.

It's also possible to simply import a data.json file like so:
import data from './data';
export default new Vuex.Store({
state: {
test: data
}
});

Related

this.$store.dispatch works but ...mapActions does not

Using vue 2 I'm trying to initialize data in vuex from a component before it loads. I can use the this.$store.dispatch and the action, along with its subsequent mutation, will run as expected from the created() function. If I call the same method in the created() function on the component using ...mapActions, the action and mutation in the module in the vuex store do not run as expected. I've looked at various ways to do this with namespacing the module (as it isn't the only module in this program), but I can't seem to get the method to run. It may be a timing in the lifecycle issue, but I'm not sure why created() wouldn't be appropriate. The addStage method is what I'm trying to have run to create the data in vuex to be displayed once the component that needs the data is loaded.
In a separate component (not shown here) I can use the ...mapActions helper by firing it from a button #click and it runs the addStage method from vuex just fine. What am I missing?
Component:
<template>
<div v-for="stage in getFlow.stages" :key="stage.id">
<flowstage v-for="step in stage.steps" :key="step.id">
<flowstep></flowstep>
</flowstage>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'flowbuildersub',
created(){
this.addStage;
//this.$store.dispatch('flowbuilder/addStage');
console.log("added stage");
},
methods: {
...mapActions('flowbuilder', ['addStage']),
},
computed: {
...mapGetters('flowbuilder', ['getFlow']),
}
}
</script>
Store:
import Vue from 'vue';
import Vuex from 'vuex';
import flowbuilder from './modules/flowbuilder.js';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
error: null,
loading: false,
information: null
},
getters: {
getError(state) {
return state.error;
},
getInformation(state) {
return state.information;
},
getLoading(state) {
return state.loading;
},
},
mutations: {
setInformation(state, payload) {
state.information = payload
},
setError(state, payload) {
state.error = payload
},
setLoading(state, payload) {
state.loading = payload
}
},
modules: {
flowbuilder
}
})
flowbuilder.js module:
export const state = {
flow: {
id: Math.ceil(Math.random()*100000000)+Math.floor(Date.now() / 1000),
name: null,
description: null,
modifiedBy: null,
stages: [],
},
};
export const getters = {
getFlow(state) {
return state.flow;
},
getStages(state) {
return state.flow.stages;
},
};
export const actions = {
addStage({ commit }) {
let defaultStep = {
id: 1,
type: "Assign",
data: null,
description: null,
subStep: null,
required: null,
selected: true,
};
let defaultStage = {
id: 1,
label: null,
description: null,
selected: false,
steps: [
defaultStep
],
};
console.log("made it here");
commit('ADDSTAGE', defaultStage);
},
};
export const mutations = {
ADDSTAGE(state, defaultStage) {
state.flow.stages.push(defaultStage);
console.log("added stage");
},
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
};

Is there a way to detect query changes using Vue-Router and successfully get new data?

I am simply making an asynchronous request to get data about a MLB player but am failing to get new data by manually changing the query parameters in the URL. When I use watch, the from and the to are the same for some reason upon debugging with Vue dev tools. However, all works well when I manually click a link to navigate routes as the from and the to correctly represent the from and the to routes.
PitcherForm.vue
export default {
name: "PitcherForm",
components: {
PlayerForm,
},
watch: {
$route() {
this.handleSubmit({ firstName: this.$route.query.firstName, lastName: this.$route.query.lastName });
}
},
methods: {
handleSubmit: function(formValues) {
// this.$store.dispatch("fetchPlayer", { formValues, router: this.$router, player: "pitching" });
this.$store
.dispatch("fetchPlayer", { formValues, player: "pitching" })
.then((promiseObject) => {
console.log(promiseObject)
this.$router.push({
// name: 'PitcherData',
path: "pitching/player",
query: {
firstName: promiseObject.firstName,
lastName: promiseObject.lastName,
},
});
})
.catch((error) => {
console.log(error);
});
},
},
//store.js
import Vue from 'vue';
import Vuex from 'vuex';
import VuexPersist from 'vuex-persist';
import axios from 'axios';
Vue.use(Vuex);
// VuexPersist stuff
const vuexLocalStorage = new VuexPersist({
key: 'vuex',
storage: window.localStorage,
});
export const store = new Vuex.Store({
plugins: [vuexLocalStorage.plugin],
state: {
playerStats: []
},
// mutations, getters, excluded for convenience
actions: {
fetchPlayer({ commit }, data) {
return new Promise((resolve) => {
let firstName = data.formValues.firstName.replace(/\s/g, "").toLowerCase();
let lastName = data.formValues.lastName.replace(/\s/g, "").toLowerCase();
axios.get(`http://localhost:5000/${data.player}/player`,
{
params: {
first: firstName.charAt(0).toUpperCase() + firstName.slice(1),
last: lastName.charAt(0).toUpperCase() + lastName.slice(1),
},
}).then(response => {
commit('setPlayers', response.data);
}).catch((error) => {
console.log(error);
});
resolve({firstName, lastName});
});
}
}
});

Nuxt Vuex State and Getters Has Data But Grayed Out

I was trying to pull data out of getters with a v-for but I kept getting nothing back so I decided to console log 'this.$store.getters.tiers' and it came back undefined.
The data shows up in the Vue Browser tab, but both State and Getters appear grayed out unless I manually click on that arrow. Is the blank data related to this, or something that I forgot in my code?
Thanks for the help!
import Vue from "vue";
import { mapGetters } from "vuex";
computed: {
tiers() {
return this.$store.getters.tiers;
},
...mapGetters(["loggedInUser"])
},
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: () => ({
tiers: [
{
id: 1,
name: "Director Subscription",
price: 25
},
{
id: 2,
name: "Regular Subscription",
price: 10
},
{
id: 3,
name: "Regular+ Subscription",
price: 15
}
],
StoreCart: []
}),
getters: {
tiers: state => state.tiers,
StoreCart: state => state.StoreCart
},
mutations: {
ADD_Item(state, id) {
state.StoreCart.push(id);
},
REMOVE_Item(state, index) {
state.StoreCart.splice(index, 1);
}
},
actions: {
addItem(context, id) {
context.commit("ADD_Item", id);
},
removeItem(context, index) {
context.commit("REMOVE_Item", index);
}
},
modules: {}
});
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn;
},
loggedInUser(state) {
return state.auth.user;
}
};
Edit: Figured it out!
I'm running Nuxt and after revising the docs, I realized that the framework already builds a lot of the objects that would otherwise need to be created when using vanilla Vuex. Below is the correct way to set up the store!
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const state = () => ({
tiers: [
{
id: 1,
name: "Director Subscription",
price: 25
},
{
id: 2,
name: "Regular Subscription",
price: 10
},
{
id: 3,
name: "Regular+ Subscription",
price: 15
}
],
StoreCart: []
});
export const mutations = {
ADD_Item(state, id) {
state.StoreCart.push(id);
},
REMOVE_Item(state, index) {
state.StoreCart.splice(index, 1);
}
};
export const actions = {
addItem(context, id) {
context.commit("ADD_Item", id);
},
removeItem(context, index) {
context.commit("REMOVE_Item", index);
}
};
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn;
},
loggedInUser(state) {
return state.auth.user;
},
tiers: state => state.tiers,
StoreCart: state => state.StoreCart
};

How to load data before create VueJS app?

I'm a little confused. How to load data (main.js file) and afrer (inside a component) set this data to data() function (calc.js)?
I have the data.json file:
{
"store_data": "VUE_STORE",
}
I have the store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
url_server: 'data.json',
store_data: '',
},
actions: {
getServerData({commit}){
return new Promise((resolve, reject) => {
Vue.http.get(this.state.url_server).then(function (response) {
if (response.status == "200") {
commit('LOAD_SERVER_DATA', response)
resolve()
}
});
});
}
},
mutations: {
LOAD_SERVER_DATA (state, response) {
this.store_data = response.data.store_data;
},
},
});
I have the main.js file:
import Vue from 'vue';
import VueResource from 'vue-resource';
import { store } from './store/store';
Vue.config.productionTip = false;
import calc from './components/calc/calc';
Vue.use(VueResource);
var app = new Vue({
el: '#app',
store,
data: {},
components: {
'calc': calc,
},
beforeCreate() {
this.$store.dispatch('getServerData');
}
});
And the component file calc.js
module.exports = {
name: 'calc',
template: `
<div>
<h1>calc</h1>
<h2>{{test_value}}</h2>
</div>
`,
data() {
return {
test_value: 'AAA',
}
},
methods: {
updateTimer() {
},
},
created() {
this.test_value = this.$store.state.store_data;
/* this.$store.dispatch('getServerData').then(() => {
this.test_value = this.$store.state.store_data;
console.log(this.$store.state.store_data);
});*/
},
computed: {
},
mounted() {
},
};
I'd like to set a test_value in calc.js file value this.$store.state.store_data. How it is possible?
Don't use data for data owned by the store. Use computed to return the store value, like so
created() {
this.$store.dispatch('getServerData');
},
computed: {
test_value(){
return this.$store.state.store_data;
}
},
mounted() {
},
And then in the vuex store the mutation has a little bug
mutations: {
LOAD_SERVER_DATA (state, response) {
state.store_data = response.data.store_data;
},

AngularJS services in Vue.js

I'm new to Vue.js and looking for the equivalent of a service in AngularJS, specifically for storing data once and getting it throughout the app.
I'll be mainly storing the results of network requests and other promised data so I don't need to fetch again on very state.
I'm using Vue.JS 2.0 with Webpack.
Thanks!
I think what u are seeking for is vuex, which can share data from each component.
Here is a basic demo which from my code.
store/lottery.module.js
import lotteryType from './lottery.type'
const lotteryModule = {
state: {participantList: []},
getters: {},
mutations: {
[lotteryType.PARTICIPANT_CREATE] (state, payload) {
state.participantList = payload;
}
},
actions: {
[lotteryType.PARTICIPANT_CREATE] ({commit}, payload) {
commit(lotteryType.PARTICIPANT_CREATE, payload);
}
}
};
export default lotteryModule;
store/lottery.type.js
const PARTICIPANT_CREATE = 'PARTICIPANT_CREATE';
export default {PARTICIPANT_CREATE};
store/index.js
Vue.use(Vuex);
const store = new Vuex.Store();
store.registerModule('lottery', lotteryModule);
export default store;
component/lottery.vue
<template>
<div id="preparation-container">
Total Participants: {{participantList.length}}
</div>
</template>
<script>
import router from '../router';
import lotteryType from '../store/lottery.type';
export default {
data () {
return {
}
},
methods: {
},
computed: {
participantList() {
return this.$store.state.lottery.participantList;
}
},
created() {
this.$store.dispatch(lotteryType.PARTICIPANT_CREATE, [{name:'Jack'}, {name:'Hugh'}]);
},
mounted() {
},
destroyed() {
}
}
</script>
You don't need Vue-specific services in Vue2 as it is based on a modern version of JavaScript that uses Modules instead.
So if you want to reuse some services in different locations in your code, you could define and export it as follows:
export default {
someFunction() {
// ...
},
someOtherFunction() {
// ...
}
};
And then import from your Vue code:
import service from 'filenameofyourresources';
export default {
name: 'something',
component: [],
data: () => ({}),
created() {
service.someFunction();
},
};
Note that this is ES6 code that needs to be transpiled to ES5 before you can actually use it todays browsers.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export