vue i18n not translate messages when locale is changed - vue.js

I'm using vue i18n to add translation to my vue app anyway after installed the cli plugin and created the translation files inside the locales folder I'm unable to switch between translations.
This is the code I've added to the navigation menu
<div class="form-inline">
<label class="px-2" for=""><i class="fas fa-globe"></i></label>
<select class="form-control" v-model="$i18n.locale">
<option v-for="(lang, i) in langs" :key="i" :value="lang">{{ lang }}</option>
</select>
</div>
And this is the realtive js code:
<script>
import bus from './main'
export default {
name: 'App',
data() {
return {
isVisible: false,
langs: ['en', 'it']
}
},
mounted() {
bus.$on('closeMenu', () => {
this.isVisible = false;
});
},
methods: {
...
}
}
</script>
I was expecting that when the user select a different locale the ui is translated but this will not happen.
The content inside my localization json file is this
// locales/en.json
{
"menuLabels": {
"loadFiles": "Load files",
"deleteFile": "Delete files",
"checkFile": "Check file"
}
}
// locales/it.json
{
"menuLabels": {
"loadFiles": "Carica files",
"deleteFile": "Elimina files",
"checkFile": "Controlla file"
}
}
into the view where I need to display the translation I've added the correct code by calling the respective translation in this way <p>{{ $t("message.loadFiles") }}</p>
Is there any problem with the code?

Related

VUE, Can't use selected option value in a select component

Im trying to use a selected option value. Can't show the value or save it.
This is my child component
`
<script>
export default {
props: {
options : {
type:Array,
},
selectOpt:undefined,
}
emits : ['input','change','option:selected']
}
</script>
<template>
<div>
<h1>
Hi, I'm a component
</h1>
<select
v-model="selectOpt"
#change="$emit('input', event.target.value)">
<option v-for="option in options"
:key="option"
>{{option}}</option>
</select>
</div>
</template>
`
This is my parent
`
<script >
import Comp from './Comp.vue'
export default {
data() {
return {
options : [1,2,3,4,5,6],
optSelected : undefined,
}
},
components: {
Comp
}
}
</script>
<template>
<Comp v-model="optSelected" :options="options"></Comp>
<p>
--->{{optSelected}}
</p>
</template>
`
I tried changin the 'input' event and 'change' event. not sure what im doing wrong.
i've found a solution that requires a vue-select library that i prefer not to use.
It's a simple detail: in vue 3, you need to use update:modelValue in order to change the v-model in parent component. (Reference: https://v3-migration.vuejs.org/breaking-changes/v-model.html)
And another thing: you souldn't use the prop as a v-model to prevent side effects in your application. You can read more about it here: https://eslint.vuejs.org/rules/no-mutating-props.html
Hope it helps:
<script>
export default {
props: {
options: {
type: Array
},
modelValue: undefined
},
emits: ['update:modelValue'],
watch: {
innerValue(newValue) {
this.$emit('update:modelValue', newValue)
},
modelValue(newValue) {
this.innerValue = newValue;
}
},
data() {
return {
innerValue: this.modelValue
};
}
};
</script>
<template>
<div>
<h1>Hi, I'm a component</h1>
<select v-model="innerValue">
<option v-for="option in options" :key="option">
{{ option }}
</option>
</select>
</div>
</template>
[Edit] Using Fallthrough Attribute:
You can use the v-bind="$atrrs":
<script>
export default {
props: {
options: {
type: Array
},
},
};
</script>
<template>
<div>
<h1>Hi, I'm a component</h1>
<select v-bind="$attrs">
<option v-for="option in options" :key="option">
{{ option }}
</option>
</select>
</div>
</template>
Read more: https://vuejs.org/guide/components/attrs.html#attribute-inheritance-on-multiple-root-nodes

Save selected values of input despite switching between two components in VUEJS

So I have two components that are imported into my app.vue:
<script>
import Leaderboard from "./components/Comp1.vue";
import Search from "./components/Comp2.vue";
export default {
name: "App",
components: {
Comp1,
Comp2,
},
}
These components are called, when I click on the corresponding button. This all works fine.
But in the components I have some input fields such as in Comp1.vue:
<template>
<div>
<select
class="form-select"
name="event"
id=""
v-model="selectedEvent"
>
<option value="">Please choose an event:</option>
<option v-for="event in eventsList" :key="event">
{{ event }}
</option>
</select>
</div>
</template>
<script>
data: function () {
return {
selectedEvent: "",
</script>
Here I can choose, which event to watch. But after switching to Comp2 and then again choosing Comp1, the selectedEvent is empty. Obviously, because its defined empty in data.
Is there any way to store the selected value in a session variable or would you prefer a different technique?
UI looks like this:
You can maintain an Object in your parent which you can pass as props to a props and then have a two way handshake
<Leaderboard :formInputs="formInputs"></Leaderboard>
<script>
import Leaderboard from "./components/Comp1.vue";
import Search from "./components/Comp2.vue";
export default {
name: "App",
components: {
Comp1,
Comp2,
},
data() {
return {
formInputs: {
compOneInput: '',
compTwpInput: ''
}
},
methods: {
updateData(payload) {
this.formInputs[payload.key] = payload.value;
}
}
and then pass this formInputs to your child Component from where you
you can emit the change whenever you update the input inside that
<template>
<div>
<select
class="form-select"
name="event"
id=""
v-model="selectedEvent"
>
<option value="">Please choose an event:</option>
<option v-for="event in eventsList" :key="event">
{{ event }}
</option>
</select>
</div>
</template>
<script>
export default {
data: function () {
return {
selectedEvent: this.formInputs.compOneInput ? this.formInputs.compOneInput : '',
}
},
watch: {
formInputs(newVal) {
this.selectedEvent = newVal.compOneInput;
},
selectedEvent(newVal, oldVal) {
if(newVal !== oldVal) {
this.$emit('updateData', {key: compOneInput, value: this.selectedEvent});
}
}
}
props: {
formInputs: Object
}
}
</script>
Using the above example for component one , you can implement the same for component two also
you can add a watcher on selectedEvent then store the data in vuex store

Unable to register custom component globally with vue.js

I have made selectbox component and wants to reuse it in other components. Si I want to register that component globally. I have imported that component in main.js but doesnot works.
main.js
import Selectbox from "#/modules/Selectbox.vue";
Vue.component("Selectbox", Selectbox);
Selectbox.vue
<template>
<div>
<label>{{ label }}</label>
<select #change="$emit('input', $event.target.value)">
<option
v-for="opt in options"
:key="opt.value"
:value="opt.value"
:selected="value === opt.value"
>
{{ errorMessage }}
{{ opt.label || "No label" }}
</option>
</select>
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
required: true
},
},
data() {
return {
errorMessage: "",
option: "lorem",
options: [
{ label: "lorem", value: "lorem" },
{ label: "ipsum", value: "ipsum" }
]
};
},
};
</script>
Test.vue
<template>
<div>
<Selectbox v-model="ward_no"/>
</div>
</template>
<script>
export default {
data() {
return {
ward_no: '',
};
}
}
</script>
There is nothing wrong in the way that you are trying to register global component but you are missing script tag.
UPDATE: After talking to #prabinasht on skype and reviewing her code, I saw that in multiple files she forgot to remove locally imported/registered component and at the same time the component was registered globally too, so that was the problem.
Register the component this way
Vue.component('Selectbox', require('#/modules/Selectbox.vue').default)

How to save and retrieve file using pouchdb and vue js

Can someone help me on how to upload a file on pouchdb and display those uploaded files on page. I want to upload a file including name info of that file. When I check the fetch files using the console I can see [object object]. Am I doing the right thing? Any advice is well appreciated. Here is my code.
//Notes.vue
// By the way Im using onsen ui for this
<template>
<v-ons-page>
<v-ons-list>
<v-ons-list-header>Auditing</v-ons-list-header>
<v-ons-list-item v-for="note in notes">
<div class="left">
<img src="" alt="">
</div>
<div class="center">
<span>{{ note._attachment['files'].data }} File here</span>
</div>
</v-ons-list-item>
</v-ons-list>
// Customize form for uploading file and info
<v-ons-alert-dialog
modifier="rowfooter"
:visible.sync="dialogVisible"
>
<span slot="title">Create a Note</span>
//File name of the file
<v-ons-input float
placeholder="Name of note"
v-model="name"
>
</v-ons-input>
// File
<v-ons-input type="file" #change="onFileChange"></v-ons-input>
<v-ons-button #click="addNotes(name)">Submit</v-ons-button>
</v-ons-alert-dialog>
</v-ons-page>
</template>
//Here the methods for uploading and reading file uploaded
<script>
import PouchDB from 'pouchdb'
var db = new PouchDB('reviewerdb')
export default {
data() {
return {
dialogVisible: false,
notes: [],
file: '',
name: '',
path
}
},
mounted() {
this.getNotes();
print('notes: ' + this.notes);
},
//Methods just adding a desciption
methods: {
onFileChange(event) {
this.file = event.target.files[0];
},
addNotes() {
db.put({
_id: 'notes',
_attachments: {
"file": {
type: this.file.type,
data: this.file
}
}
})
},
getNotes() {
db.get('notes', {attachments:true}).then(function (note) {
this.notes = note;
});
}
}
}

How can I upload image in a link on the vue component?

My component vue like this :
<template>
<div>
<ul class="list-inline list-photo">
<li v-for="item in items">
<div class="thumbnail" v-if="clicked[item]">
<img src="https://myshop.co.id/img/no-image.jpg" alt="">
<span class="fa fa-check-circle"></span>
</div>
<a v-else href="javascript:;" class="thumbnail thumbnail-upload"
title="Add Image" #click="addPhoto(item)">
<span class="fa fa-plus fa-2x"></span>
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['state', 'product'],
data() {
return {
items: [1, 2, 3, 4, 5],
clicked: [] // using an array because your items are numeric
}
}
},
methods: {
addPhoto(item) {
this.$set(this.clicked, item, true)
}
}
}
</script>
If I click a link then it will call method addPhoto
I want if the a link clicked, it will upload image. So it will select the image then upload it and update img with image uploaded.
It looks like the code to upload image will be put in add photo method
I'm still confused to upload image in vue component
How can I solve it?
You can use a component for file picker like this:
<template>
<input v-show="showNative" type="file" :name="name" #change="onFileChanged" :multiple="multiple" :accept="accept"/>
</template>
<script>
export default {
props: {
name: { type: String, required: true },
show: { type: Boolean, Default: false },
multiple: { type: Boolean, default: false },
accept: { type: String, default: "" },
showNative: { type: Boolean, default: false }
},
watch: {
show(value) {
if (value) {
// Resets the file to let <onChange> event to work.
this.$el.value = "";
// Opens select file system dialog.
this.$el.click();
// Resets the show property (sync technique), in order to let the user to reopen the dialog.
this.$emit('update:show', false);
}
}
},
methods: {
onFileChanged(event) {
var files = event.target.files || event.dataTransfer.files;
if (!files.length) {
return;
}
var formData = new FormData();
// Maps the provided name to files.
formData.append(this.name, this.multiple ? files : files[0]);
// Returns formData (which can be sent to the backend) and optional, the selected files (parent component may need some information about files).
this.$emit("files", formData, files);
}
}
}
</script>
And here some information how to use it:
import the component -> declare the directive.
provide a -> is used for the formData creation (is the name which is going to backend).
to display it us the property
Note: sync recommended if needed to be opened multiple times in the same page. Check the bottom examples. ( /!\ Vue 2.3 required for sync /!\ )
listen to #files event to get an array of selected files as parameter
if you want to use it as multiple file select, then provide the property as true.
use prop to filter the files (valid accept types: HTML Input="file" Accept Attribute File Type (CSV)).
when is set to true, the component displays 'select file' button (input type file), otherwise it is hidden, and windows displayed by Js.
ex:
Single select
<file-upload name="fooImport" #files="selectedFile" :show.sync="true" />
ex:
Multiple select
<file-upload name="barUpload" #files="selectedFiles" :show.sync="displayUpload" accept="text/plain, .pdf" />