Laravel & Vuejs mixins : how to attribute a new value to shared variable? - laravel

I can use the mixin variables test and the method changeTest, when when I attribute a new value to the variable test, it's only applied in one component. How to have it changed globally, on all components using it ?
My mixins are set in the file resources/js/mixins.js:
export default {
data() {
return {
test: 'foo',
};
},
methods: {
changeTest(v) {
this.test = v;
}
}
}
Then, I have my two components comp1.vue and comp2.vue in resources/js/components/, both looking like this:
<template>
<div>
{{ test }}
</div>
</template>
<script>
import myMixins from '../mixins'
export default {
mixins: [ myMixins ],
}
</script>
Both components are in my home.blade.php like this:
#extends('layouts.app')
#section('content')
<comp1></comp1>
<comp2></comp2>
#ensection

for making a common variable (state) between all instances in vue.js you can use vuex. it's so simple, just add vuex to your packages and make an instance like this:
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
test: 'foo',
},
mutations: {
setTest(state, payload) {
state.test = payload
}
},
});
now you need to add this store to your main vue instance:
import Vue from 'vue'
Vue.use(Vuex);
let vm = new Vue({
el: '#app',
store,
// ...
});
all done. now in every component you can access the states by this.$store.state. for making life easier, you can define a computed variable like this:
computed: {
test() {
return this.$store.state.test
}
}
to change the state you just need to commit the setTest mutation. you have to add this mutation to methods and simply call it like this:
methods: {
...Vuex.mapMutations(['setTest']),
myMethod() {
// do this
this.setTest('some value');
// do that
}
}
you can also make a global mixin like i told you before to add this computed and mutation to every instance like this: (add this before make the main vue instance)
Vue.mixin({
computed: {
test() {
return this.$store.state.test
}
},
methods: {
...Vuex.mapMutations(['setTest']),
}
});
but i don't recommend to do this because when the project grow big, it gets so hard to avoid name confusion. it's better to make them separately for each component to chose proper names.

you can use mixin method on main Vue instance like this:
import Vue from 'vue'
import MyMixin from './mixins.js'
Vue.mixin(MyMixin);
It will apply this mixin for all instance no matter how deep they are.

Related

Vue 3: How to implement a function that modifies all input fields in the DOM?

I'm new to Vue and want to add an onfocus function to all input fields. When I use mixin, the function is called every time a component is mounted.
createApp(App).mixin({
mounted() {
myFunction() {
document.querySelectorAll('input').doSomething()
}
}
}).mount('#app');
That makes sense and is in generally what I want, because newly added input fields should be affected, too. But then the function would iterate through the whole DOM every time a component is mounted, right? I want to avoid unnecessary iteration for fields that already have the onfocus function. So what would be best practice to do something like this?
import { createApp, h } from "vue";
import App from "./App.vue";
const app = createApp({
render: () => h(App)
});
app.mixin({
methods: {
myFunction() {
this.$el.querySelectorAll("input").forEach((el) => {
alert(el.getAttribute("name"));
});
}
},
mounted() {
this.myFunction();
}
});
app.mount("#app");

Create global method vue on app.js laravel

I want create global method to translate message using Laravel-JS-Localization
But when i call the method using vue mustache got an error like this:
Property or method "trans" is not defined on the instance but referenced during render.
Make sure that this property is reactive.
Here my laravel app.js code:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('dashboard', require('./components/Dashboard').default);
const app = new Vue({
el: '#vue',
methods: {
trans: function (key) {
return Lang.get(key);
},
},
});
Dashboard.vue code :
<template>
<p>{{ trans('common.welcome') }}</p>
</template>
<script>
data () {
return {
name: '',
}
},
</script>
dashboard.blade.php code :
..........
<div class="col-9" id="vue">
<dashboard></dashboard>
</div> <!--c end col-8 -->
..........
I would probably go with creating a Plugin. For example
Vue.use({
install (Vue) {
Vue.prototype.$trans = Lang.get
}
})
Adding this to your app.js code before creating any components or new Vue({...}) will mean all your components will have access to the $trans method.
Alternatively, you can create a Global Mixin but these aren't strongly recommended.
Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components
Vue.mixin({
methods: {
trans (key) {
return Lang.get(key)
}
}
})

How to set value in component from ajax request to parameters during creation in Vue?

I am learning Vue and trying to set one value in component during its creation from one Ajax request.
Here is the structure of src folder:
src
assets
components
Management.vue
router
index.js
vuex
modules
caseSuiteList.js
index.js
actions.js
getters.js
App.vue
main.js
Management.vue:
<template>
</template>
<script>
import {mapState} from 'vuex'
import store from 'vuex'
export default {
name: "Management",
computed: mapState({
suite_list: state => state.caseSuiteList.suite_list
}),
created(){
store.dispatch('refresh')
}
}
</script>
caseSuiteList.js:
import axios from 'axios'
const state = {
suite_list : {}
}
const mutations = {
refreshSuiteList(state, payload) {
state.suite_list = payload
}
}
const actions = {
refresh (context) {
axios.get('http://127.0.0.1:8601/haha').then(function(res){
console.log(res.data);
context.commit('refreshSuiteList', res.data);
}
});
}
}
export default {
state,
mutations,
actions
}
How to dispatch action of caseSuiteList.js in created() of Management.vue to make this happen?
Within the vue instance (or any component within) you access the store with this.$store.
Try dispatching in the created hook of your component.
created() {
this.$store.dispatch('refresh');
}
More information about Vuex: https://vuex.vuejs.org/guide/actions.html

Vue + axios returns undefined

I have app.js importing axios and VueAxios as:
Vue.use(VueAxios, axios);
Then calling my component:
Vue.component('api-call', require('./components/PostComponent'));
In my PostComponent I have a simple axios get as follows:
<script>
export default {
// name: "PostComponent"
data() {
return {
post: {},
}
},
methods: {
getPosts: () => {
console.log('started');
//let that = this;
let uri = 'https://jsonplaceholder.typicode.com/posts';
this.axios.get(uri).then((response) => {
console.log(response);
})
}
},
mounted(){
this.getPosts()
}
}
</script>
Since I want this executed right at the start of the component loading I am using mounted (why Vue don't have a constructor baffles me, even react passed on the isMounted pattern.)
What am I doing wrong?
thanks,
Bud
You can't use arrow function for methods declaration.
See https://v2.vuejs.org/v2/api/#methods
Note that you should not use an arrow function to define a method
(e.g. plus: () => this.a++). The reason is arrow functions bind the
parent context, so this will not be the Vue instance as you expect and
this.a will be undefined.
These are the 2 ways to properly define a method
1.
getPosts: function() {
}
(if you can use ES6)
getPosts() {
}

How do I use vue-resource v-links inside a vueify component?

When using v-link="{ path: '/add' }" in my vueify (used with Laravel) component, I get a v-link can only be used inside a router-enabled app. or a <router-view> can only be used inside a router-enabled app. error.
Here is my main.js: http://laravel.io/bin/Kkj27
My code seems very similar to the example provided for nestedRoutes, I am not sure why this is not working.
This is all a little confusing to me (best practices for structuring Vue.js single page apps) but this is essentially what I did to make it work:
Vue.component('Todo', Todo);
And removing this whole thing:
var TodoApp = new Vue({
el: '#app',
components: { Todo }
});
After this, I can refer to the Todo component in the router.map function.
router.map({
'/': {
component: Todo,
subRoutes: {
'/bar': {
...
},
'/baz': {
...
}
}
}
})

Resources