I want to pass a value from my vue instance to my vue component.
I have following vue component (vuejs dropzonejs component), which das basically a nice Image upload ui.
<template>
<vue-dropzone ref="myVueDropzone" id="dropzone" :options="dropzoneOptions"></vue-dropzone>
</template>
<script>
import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.css'
export default {
name: 'app',
components: {
vueDropzone: vue2Dropzone
},
data: function() {
return {
game: {
title: ''
},
dropzoneOptions: {
url: '/games/upload',
method: 'post',
params: {
title: this.game.title
}
}
}
},
methods: {
processFiles () {
this.$refs.myVueDropzone.processQueue();
},
getGameTitle () {
this.game.title = '',
}
}
}
</script>
I Need to get the game title from my vue instance and pass it to my vue component so that I can do some work there with that title.
My vue instance Looks like this:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('vue-dropzone', require('./components/ImageDropzoneComponent.vue'));
const app = new Vue({
el: '#app',
data: {
loading: false,
title: '',
},
methods: {
createGame (e) {
this.uploadImage();
axios.post('/games', {
title: this.title,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
},
uploadImage () {
this.$refs.myVueDropzone.processFiles()
},
getGameTitle () {
return this.title;
}
}
});
The tag:
<vue-dropzone ref="myVueDropzone"></vue-dropzone>
Related
My app structure:
> public
> scripts
> - cdn
> - vue.js
> - vuex.js
> main.js
> store.js
> index.html
Inside the head tag I have:
<script src="./scripts/cdn/vue.js"></script>
<script src="./scripts/cdn/vuex.js"></script>
<script src="./scripts/main.js" type="module"></script>
And in the body I have-
<div id="app"> <div v-for="item in items" >{{item.text}}</div> </div>
store.js
console.log('test in store.js', store.state)
const store = new Vuex.createStore({
state: {
items: [{
text: 'ahhh STORE 1'
}, {
text: 'ahhh STORE 2'
}],
},
mutations: {
},
actions: {
test({
state
}) {
console.log(state.items)
}
},
modules: {
}
})
main.js
import * as store from "./store.js";
const {
onMounted,
onUpdated,
onUnmounted,
ref,
reactive,
getCurrentInstance
} = Vue; //here define only what you need
//Define Vue app
const App = {
state: store,
// store, //using either store or state: store does not work
data() {
return {};
},
methods: {},
setup(props, context) {
onMounted(() => {
console.info("App mounted!");
console.log('mounted state', store.state)
});
onUpdated(() => {
console.info("App updated!");
});
onUnmounted(() => {
console.info("App unmounted!");
});
}
};
// Create new Vue app
const app = Vue.createApp(App);
app.use(store)
app.mount("#app");
So when the app runs, in the console it shows
test in store.js Proxy { <target>: {…}, <handler>: {…} }
But in onMounted it returns store.state as undefined.
It can work by using createStore inside main.js but I would like to keep this separated.
What am I missing and how do I make the store accessible in the main?
app.use(store) -
you have already added the store to the vue instance.
Then you can access this storage from any component, for example using:
import { mapState} from 'vuex';
...
computed: {
...mapState({
items: state => state.items
}),
},
or in setup:
import { useStore } from 'vuex';
...
setup(){
const store = useStore();
const state = store.state; // <-- state from vuex
}
Your working example:
const store = new Vuex.createStore({
state: {
items: [{
text: 'ahhh STORE 1'
}, {
text: 'ahhh STORE 2'
}],
},
mutations: {
},
actions: {
test({
state
}) {
console.log(state.items)
}
},
modules: {
}
})
const {
onMounted,
onUpdated,
onUnmounted,
ref,
reactive,
} = Vue; //here define only what you need
//Define Vue app
const App = {
data() {
return {};
},
methods: {},
computed: {
...Vuex.mapState({
items: state => state.items
}),
},
setup(props, context) {
const store = Vuex.useStore()
onMounted(() => {
console.info("App mounted!");
console.log('mounted state', store.state)
});
onUpdated(() => {
console.info("App updated!");
});
onUnmounted(() => {
console.info("App unmounted!");
});
}
};
// Create new Vue app
const app = Vue.createApp(App);
app.use(store)
app.mount("#app");
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vuex#4.0.0/dist/vuex.global.js"></script>
<div id="app">
<div v-for="item in items">{{item.text}}</div>
</div>
I have a laravel collection that should pass json data to a vue component
$problems = $maintenance->getMaintenanceTypes();
return new MaintenanceTypesCollection($problems);
I'm then creating a radio button using that json collection
<div v-for="m_type in maintenance_types" :key="m_type.id">
<input type="radio" v-model="form.m_type" :value="m_type.id" :id="m_type.id">
<label :for="m_type.id">{{ m_type.problem }}</label>
</div>
and the data is being passed well when I'm using Laravel web routing but when I switch to Vue router the data is not being passed at all.
For reference here is my routes/api.php
Route::get('/maintenance/types', 'Maintenance\MaintenanceTypesController#index');
Here is my Vuex store
import axios from 'axios'
import { data } from 'jquery'
export default {
namespaced: true,
state:{
maintenance_types: []
},
getters:{
maintenance_types (state) {
return state.maintenance_types
}
},
mutations:{
PUSH_M_TYPE (state, data) {
state.maintenance_types.push(...data)
}
},
actions:{
async getMaintenanceTypes ({ commit }) {
let response = await axios.get('/maintenance/types')
commit('PUSH_M_TYPE', response.data.data)
}
}
}
And here is my Vue component script logic
import { mapGetters, mapActions } from 'vuex'
import axios from 'axios'
export default {
data () {
return {
form: {
description: '',
m_type: ''
}
}
},
computed: {
...mapGetters({
maintenance_types: 'maintenance/maintenance_types'
})
},
methods: {
...mapActions({
getMaintenanceTypes: 'maintenance/getMaintenanceTypes'
}),
async submit () {
await axios.post('/api/maintenance/store', this.form)
}
},
mounted () {
this.getMaintenanceTypes()
}
}
When I'm using this Vue routing it is not working
import AppMaintenanceForm from './components/maintenance/AppMaintenanceForm.vue'
export const routes = [
{
path: '/maintenance/form',
component: AppMaintenanceForm,
name: 'MaintenanceForm'
},
]
but when I switch to Laravel's routes/web.php it is working. What could be the problem? Thanks.
I would like to test if my getter is called in my component or view, but I don't understand how can it.
My method in the component :
computed: {
...mapGetters({ item: 'moduleA/getData' }),
},
And this is my unit test declaration :
beforeEach(() => {
store = new Vuex.Store({
modules: {
moduleA: {
state: {},
getters: {
getData() {
return { item: { name: 'test' } };
},
},
},
},
});
wrapper = shallowMount(MyComponent, {
store,
});
});
And I try to test if the data is loaded in my template:
it('should check if name is thruthy', () => {
expect(wrapper.find('.classA').text()).toEqual('test');
});
my component :
<template>
<v-content>
<ComponentA v-if="item.name"
key="keyA" ></ComponentA>
<ComponentB v-else key="keyA"></ComponentB>
</v-content>
</template>
<script>
import { mapGetters } from 'vuex';
import ComponentA from '#/components/ComponentA.vue';
import ComponentB from '#/components/ComponentB.vue';
export default {
/**
* Component's name :
*/
name: 'ViewA',
/**
* Component's used :
*/
components: {
ComponentA,
ComponentB,
},
/**
* computed's used :
*/
computed: {
...mapGetters({ item: 'moduleA/getData' }),
},
};
</script>
and my getter in the moduleA :
const getters = {
getData: state => state.data,
};
But I have this message:
TypeError: Cannot read property 'name' of undefined
Why? Thank you for your help.
As shown in docs, shallowMount's options has field named localVue. To solve your problem you should create a localVue, using createLocalVue and pass it to shallowMount.
createLocalVue returns a Vue class for you to add components, mixins
and install plugins without polluting the global Vue class.
import Vuex from 'vuex'
import { createLocalVue, shallowMount } from '#vue/test-utils'
beforeEach(() => {
const localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
moduleA: {
state: {},
getters: {
getData() {
return { item: { name: 'test' } }
},
},
},
},
})
wrapper = shallowMount(MyComponent, {
localVue,
store,
})
})
I'm using vue-chartjs with Laravel, and I have a problem where the data isn't loaded when on load. But when I click 3x on Legend the data shows up.
Here is gif: https://gfycat.com/gifs/detail/SimilarShockedAffenpinscher
My code:
<template>
<Chart :chartData="this.data" :width="800" :height="500"></Chart>
</template>
<script>
import Chart from './Chart.vue';
export default {
name: 'home',
components: {
Chart
},
data() {
return {
data: {},
weights: [],
dates: []
}
},
mounted () {
this.render()
},
methods: {
render() {
self = this
axios.get('/api/data')
.then(function (response) {
for (var i = 0; i < response.data.data.length; i++) {
self.weights.push(response.data.data[i].kg)
self.dates.push(response.data.data[i].created_at)
}
console.log(response)
})
.catch(function (error) {
console.log(error);
});
// Overwriting base render method with actual data.
self.data = {
labels: self.dates,
datasets: [
{
label: 'Data One',
data: self.weights,
}
]
}
}
}
}
</script>
Chart.vue:
<script>
import VueCharts from 'vue-chartjs'
import { Bar, Line, mixins } from 'vue-chartjs'
import moment from 'moment'
import axios from 'axios'
export default {
extends: Bar,
mixins: [mixins.reactiveProp],
props: ['chartData', 'options'],
data() {
return {
}
},
mounted () {
this.renderChart(this.chartData, this.options)
},
methods: {
}
}
</script>
I suspect this is your problem:
self.data = {
labels: self.dates,
datasets: [
{
label: 'Data One',
data: self.weights,
}
]
}
Self is referencing this so self.data = this.data. it's assigning directly to your components data property.
I need import component with data into vue.js app.
I can component registration and I used this code.
Correct Code:
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
components: {
'test': {
template: '<div>msg: {{message}}</div>',
props: {
message: {
type: String,
required: true
}
}
}
}
}
But how can I Local Registration with data?
NOT correct:
import Test from './components/Test.vue';
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
components: {
'test': {
template: Test,
props: {
message: {
type: String,
required: true
}
}
}
}
}
This should work
import Test from './components/Test.vue';
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
components: {
Test
}
}
And if you want to pass props
<template>
<Test :message=msg></Test>
</template>
I use props in component code (components/xxx.vue) and resolved it.