How to use global functions VUE 2 CLI? - javascript

few of my components are using same functions, is there a way how don't to copy code to each component but use it globally...?
If you just put the function in the App.vue, then it is still not available in the component...

Write a separate page with the same functionality, and then introduce it where it is needed.
<template>
<div class='demo'>
<module></module>
</div>
</template>
<script>
import module from './components/module'
export default {
components:{module},
data() {
return {
};
},
methods: {
},
created() {
},
mounted() {
},
}
</script>
<style lang='less' scoped>
</style>

Related

Vue - Access prop in child component, regular javascript

I am loading a Vue component from another Vue component and am passing a property to that component. I need to access this property in the regular javascript of that component, but cannot figure out how to do this.
The simplified parent component could look as follows:
<template>
<div>
<MenuEdit :menu-list="menuList"></MenuEdit>
</div>
</template>
<script>
import MenuEdit from '#/components/MenuEdit';
export default {
name: 'Admin',
data: function () {
return {
menuList: ["Item1","Item2","Item3","Item4"]
};
},
components: {
MenuEdit
}
}
</script>
<style scoped>
</style>
And the MenuEdit could look as follows:
<template>
<div>
{{ menuList }}
</div>
</template>
<script>
//console.log(this.menuList) // Does not work.
export default {
name: 'MenuEdit',
props: [
'menuList'
],
methods: {
testMenu: function() {
console.log(this.menuList) //This works fine
}
}
}
</script>
<style scoped>
</style>
EDIT
To add some context to the question, I am implementing sortablejs on Buefy using the following example: https://buefy.org/extensions/sortablejs
Instead of calling "vnode.context.$buefy.toast.open(Moved ${item} from row ${evt.oldIndex + 1} to ${evt.newIndex + 1})" at the end of the first const, I want to update the component (or better said, update the related Array).
In the example, the const are defined outside of the component, which is why I ended up with this question.
You cannot access the prop as that code (where your console.log is) runs before the component is mounted, before it's even declared really
If you want to access stuff when the component is first mounted, you can use the mounted lifecycle method

how to export tags and computed functions to main App.vue from components in VueCLI

I'm at the very start with VUE CLI 3, and was wondering if I could make clean my code importing from the components to the main App.vue such things like tags inside the template of those components, or even computed functions of that components, here on detail my problem:
This is one of my components (header), and I want to export that input tag and its computed function to the main App.vue without precisely write all that template code and scripts in there.
<template>
<div>
<input type='text' v-model='search' placeholder='Search for Tittle or Author'/>
</div>
</template>
<script>
export default {
name:"header",
props:{
header:Object
},
computed: {
filteredTitles:function()
{
return this.bookLists.filter((data)=>{return data.title.toUpperCase().includes(this.search.toUpperCase())})
}
}
}
</script>
This is my App.Vue file already with that component imported, but the point is even the element already was imported , the input doesn't show up, unless I write its code inside the App.vue template tag in fact.
<template>
<div id="app">
<div class="card-flipping">
<books v-for="(books,index) in bookLists" v-bind:key="index" v-bind:books="books" />
</div>
</div>
</template>
<script>
import books from "./components/books.vue";
import header from './components/header.vue';
export default {
name: "app",
components: {
header,
books,
},
data() {
return {
bookLists: []
};
},
methods: {
getJsonData() {
fetch(" https://api.myjson.com/bins/zyv02 ", {
method: "GET"
})
.then(response => {
return response.json();
})
.then(bookStore => {
this.bookLists = bookStore.books;
})
.catch(error => {
console.log(error);
});
}
},
computed: {
filteredTitles:function()
{
return this.bookLists.filter((data)=>{return data.title.toUpperCase().includes(this.search.toUpperCase())})
}
},
created() {
this.getJsonData();
}
};
</script>
Could somebody help me please?

Vue - Apply "v-model" on user-defined component which use ace-editor

Code
CodeEditor.vue:
<template>
<div class="ace-container">
<div class="ace-editor" ref="ace"></div>
</div>
</template>
<script>
import ace from 'ace-builds'
import 'ace-builds/webpack-resolver'
import 'ace-builds/src-noconflict/theme-monokai'
import 'ace-builds/src-noconflict/mode-javascript'
export default {
mounted() {
this.aceEditor = ace.edit(this.$refs.ace, {
maxLines: 60,
minLines: 10,
fontSize: 14,
theme: this.themePath,
mode: this.modePath,
tabSize: 4
})
},
data() {
return {
aceEditor: null,
themePath: 'ace/theme/monokai',
modePath: 'ace/mode/javascript'
}
},
methods: {
setCode(code) {
this.aceEditor.setValue(code);
},
getCode() {
return this.aceEditor.getValue();
},
}
}
</script>
<style>
.ace-editor {
width: 600px;
height: 600px;
}
</style>
QuizExecution.vue: (partly)
<template>
<v-app height="100%">
<div id="qz-wrapper">
<!--
<v-textarea id="programmingText" v-model="answerData[question.id]"
#change="saveAnswer(qe.id, question.id)" label="Code" outlined></v-textarea>
-->
<CodeEditor id="programmingText" v-model="answerData[question.id]"
#change="saveAnswer(qe.id, question.id)"></CodeEditor>
</div>
</v-app>
</template>
<script>
import Vue from 'vue'
import CodeEditor from "./CodeEditor";
export default {
components: {CodeEditor},
data() {
return {
// ..
}
}
}
</script>
<style scoped>
</style>
Description
With vuetify's <v-textarea>, I can use v-model to bind its content to a data property, in bi-direction dynamically, so that could init on load, and save on change with a #change property.
Then I want to replace the input area with ace-editor, which support features like syntax highlight.
So, I have defined a component as in CodeEditor.vue, then import & use it in QuizExecution.vue.
But, the v-model and #change won't work on the <CodeEditor> tag.
Questions
How to apply v-model and #click on this <CodeEditor> with in QuizExecution.vue.
Aka. init it with data from container component, and retrieve its content on change and trigger an event to save.
Or, is there anyway to achieve the same result: init on creation & save on change.
You can use props and watch the change events with #update_question_id;
<CodeEditor id="programmingText" :question_id="answerData[question.id]"
#update_question_id="answerData[question.id]=#event"
></CodeEditor>
....
watch:{
answerData(){
saveAnswer(this.qe.id, this.question.id)
}
}
CodeEditor.vue:
You can get the question_id value with props. I think it would be string or number.
And also watch question_id then use $emit to send change $event to main component.
export default {
props:{
question_id: [String,Number]
},
watch:{
question_id(val){
this.$emit("update_question_id",val)
}
}
.....

Why wont the component respond to the custom event?

I am emitting an event called emit-event-main2-counter in Main2.vue
Why will the data cntr in Bottom.vue not update?
App.vue
<template>
<div class="app">
<Main2 />
<Bottom/>
</div>
</template>
<script>
import Main2 from "./components/Main2";
import Bottom from "./components/Bottom";
export default {
components: {
Main2,
Bottom
},
}
</script>
<style scoped>
h1 {
color: red;
}
</style>
Main2.vue
<template>
<div>
main2 template <span class="text1">{{message}}</span>
<button type="button" v-on:click="btnClickButton">my click</button>
<div>{{counter}}</div>
</div>
</template>
<script>
import appInput from "./appInput.vue";
export default {
data: () => {
return {
message: "theText",
counter: 0,
}
},
components: {
appInput,
},
methods: {
btnClickButton(e) {
this.$root.$emit('emit-event-main2-counter', this.counter)
console.log('button');
this.counter +=1;
}
}
}
</script>
<style scoped>
.text1 {
color:red;
}
.text2 {
color:blue;
}
</style>
Bottom.vue
<template>
<div class="Bottom" v-on:emit-event-main2-counter="cntr = $event">
bottom text and cntr ({{cntr}})
</div>
</template>
<script>
export default {
data: () => {
return {
cntr: 0
}
},
}
</script>
<style scoped>
</style>
You could emit an event to parent from Main2 having as parameters this.counter and in the parent one receive that and pass it through props to Bottom
In Main2 :
this.$emit("emit-event-main2-counter",this.counter);
in the parent component :
<template>
<Main2 v-on:emit-event-main2-counter="sendToBottom"/>
<Bottom :cntr="pcounter"/>
....
</template>
data:{
pcounter:0
},
methods:{
sendToBottom(c){
this.pcounter=c
}
}
Bottom should have property called cntr
props:["cntr"]
Bottom.vue
<template>
<div class="Bottom" >
bottom text and cntr ({{cntr}})
</div>
</template>
<script>
export default {
props:["cntr"],
data: () => {
return {
}
},
}
</script>
If you want to use root events, you need to emit the event with this.$root.$emit() and also listen to the event on the root like this: this.$root.$on().
You should use it directly in the script part. Listen to the root event e.g. in the created() hook and then disable it with $off in the beforeDestroy() hook.
However, I wouldn't encourage you to use $root events. It is usually better to communicate between the components like #BoussadjraBrahim proposed in his answer.
If you have a more complex application, it makes sense to take a look at Vuex and store the complete state in the Vuex store. By doing this, you can watch the global application state in the components and react if it changes. In this scenario, you would use the Vuex store instead of a root EventBus.

How to use in imported function in template?

I currently run into the issue that my imported function is not referenced during render. It's easier explained by this code:
<template>
<div v-for="(addOn, index) in JSON.parse(this.restaurants[0].categories[categoryId].addons)">
<label>
<span>{{ addOn.name }} (+ ${{ addZeroes(addOn.price) }})</span>
</label>
</div>
</template>
<script>
import { addZeroes } from "../../../js/helpers";
export default {
data() {
return {
// populated via AJAX
restaurants: [
{
categories: []
}
],
}
},
}
</script>
<style>
</style>
and the error is:
[Vue warn]: Property or method "addZeroes" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
What's the proper way to call a helper function inside a Vue template?
Thanks for any hints!
You could add it to your component:
import { addZeroes } from "../../../js/helpers";
export default {
data() {
return {
// populated via AJAX
restaurants: [
{
categories: []
}
],
}
},
methods: {
addZeroes // shorthand for addZeroes: addZeroes
}
}

Categories

Resources