Data not updating properly on i18n lang switch - vue.js

On my index page, loading it for the first time returns the correct data I need:
index.js
<script>
export default {
async asyncData({ store, i18n }) {
let lang
if (i18n.locale == "en") lang = 'en'
if (i18n.locale == "pt") lang = 'pt-PT'
if (i18n.locale == "fr") lang = 'fr'
try {
const services = await (await fetch(`${store.state.apiUrl}/project-categories?populate=*&locale=` + lang)).json()
const projects = await (await fetch(`${store.state.apiUrl}/projects?populate=*&locale=` + lang)).json()
const articles = await (await fetch(`${store.state.apiUrl}/articles?populate=*&locale=` + lang)).json()
console.log(projects.data)
return {
projects: projects.data,
articles: articles.data,
services: services.data
}
} catch (error) {
console.log(error)
}
}
}
</script>
Returned data in default english looks like this:
[
{
id: 1,
attributes: {
title: 'Space RTS Game',
slug: 'space-rts-game',
intro: 'A Space Real-Time-Strategy MMO Game Project ...',
body: '',
subtitle: 'Game Development',
createdAt: '2022-06-13T15:09:23.144Z',
updatedAt: '2022-06-16T11:42:58.215Z',
publishedAt: '2022-06-16T11:42:58.209Z',
locale: 'en',
cover: [Object],
images: [Object],
localizations: [Object]
}
},
(...)
]
But once I switch the lang to fr, the data is returned as observers:
Here is the used html for switching lang:
<template>
<nav>
<ul class="nav justify-content-end">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="javascript:void(0)" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ $root.$i18n.locale }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<nuxt-link
v-for="locale in availableLocales"
:key="locale.code"
:to="switchLocalePath(locale.code)"
class="dropdown-item">{{ locale.name }}
</nuxt-link>
</div>
</li>
</ul>
</nav>
</template>
(...)
<script>
export default {
computed: {
availableLocales () {
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale)
}
}
}
</script>
If I try to copy this (observers) object from my browser console into a text editor, I've got these results which is much more complex (but shows the translated data in french inside):
[
{
"id": 4,
"attributes": {
"title": "Jeu Spatial RTS",
"slug": "jeu-spatial-rts",
"intro": "Un projet de jeu MMO de stratégie en temps réel spatial utilisant des ressources basées sur NFT Casper - La plupart des éléments de conception du jeu sont déjà terminés. Le développement commence bientôt...",
"body": null,
"subtitle": "Dev. de Jeu",
"createdAt": "2022-06-16T08:33:39.761Z",
"updatedAt": "2022-06-16T18:09:49.524Z",
"publishedAt": "2022-06-16T11:44:12.561Z",
"locale": "fr",
"cover": {
"data": {
"id": 2,
"attributes": {
"name": "cover-surface-lg.jpg",
"alternativeText": "cover-surface-lg.jpg",
"caption": "cover-surface-lg.jpg",
"width": 370,
"height": 240,
"formats": {
"thumbnail": {
"name": "thumbnail_cover-surface-lg.jpg",
"hash": "thumbnail_cover_surface_lg_6b09d070dd",
"ext": ".jpg",
"mime": "image/jpeg",
"path": null,
"width": 240,
"height": 156,
"size": 10.98,
"url": "/uploads/thumbnail_cover_surface_lg_6b09d070dd.jpg"
}
},
"hash": "cover_surface_lg_6b09d070dd",
"ext": ".jpg",
"mime": "image/jpeg",
"size": 21.62,
"url": "/uploads/cover_surface_lg_6b09d070dd.jpg",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"createdAt": "2022-06-13T15:19:23.234Z",
"updatedAt": "2022-06-13T15:19:23.234Z"
}
}
},
"images": {
"data": null
},
"localizations": {
"data": [
{
"id": 1,
"attributes": {
"title": "Space RTS Game",
"slug": "space-rts-game",
"intro": "A Space Real-Time-Strategy MMO Game Project using NFTs Casper based assets - Most of the game design parts are already done. Development starting soon...",
"body": "",
"subtitle": "Game Development",
"createdAt": "2022-06-13T15:09:23.144Z",
"updatedAt": "2022-06-16T11:42:58.215Z",
"publishedAt": "2022-06-16T11:42:58.209Z",
"locale": "en"
}
},
{
"id": 5,
"attributes": {
"title": "Jogo RTS Espacial",
"slug": "jogo",
"intro": "Um projeto de jogo MMO de estratégia em tempo real espacial usando recursos baseados em NFTs Casper - A maioria das partes de design de jogos já está pronta. Desenvolvimento começando em breve...",
"body": null,
"subtitle": "Jogo Dev.",
"createdAt": "2022-06-16T08:34:11.701Z",
"updatedAt": "2022-06-16T18:10:08.725Z",
"publishedAt": "2022-06-16T11:44:18.058Z",
"locale": "pt-PT"
}
}
]
}
}
},
(...)
As you can notice, it starts now at id: 4 and page text in my page just disappeared once I switched the lang. I'm a beginner with Nuxt / Vue.Js and would be curious why this is happening and find clues on how to resolve that problem.
Thanks in advance!

Related

TypeError: $data.quotation.company is undefined

I have problem when I try to render data in my Vue3 application.
data() {
return {
quotation: [],
}
},
mounted() {
this.getQuotation()
},
methods: {
async getQuotation() {
this.$store.commit('setIsLoading', true)
const quotationID = this.$route.params.id
await axios
.get(`/api/v1/quotations/${quotationID}/`)
.then((response) => {
this.quotation = response.data
})
.catch(error => {
console.log(error)
})
},
}
The weird part is when I try to access {{quotation.company}} in template I can see the element of "company" without any error. The error TypeError: $data.quotation.company is undefined occurs when I get in depth {{quotation.company.name}} for example.
Axios is getting data like:
{
"id": 20,
"company": {
"id": 4,
"name": "xxxx",
"slug": "xxx",
"categories": [
{
"id": 7,
"name": "xxxx",
"slug": "xxxx"
}
],
"street2": "",
"postcode": 11111,
},
"home_type": "xxxx",
"Urgency": "",
"description": "xxxx",
}
I really don't understand :/
First the quotation property should be declared as an object like quotation: {}, then at the first rendering the field company is not available yet, so you need to add some conditional rendering as follows :
<div v-if="quotation.company" >
{{quotation.company.name}
</div>

Vuejs get dynamic form values

I have select and input component with made by buefy. Everything is ok till I realize how can I get the data.
I'm sort of new on vuejs. So I will be glad if you help me out.
I'm getting dynamic form from backend
So my question is how can get values these inputs and submit to backend again with getOffer() methot.
Here is my codes;
Input.vue
<template>
<b-field :label="fieldLabel">
<b-input
:name="inputName"
:type="inputType"
:maxlength="inputType == 'textarea' ? 200 : null"
></b-input>
</b-field>
</template>
<script>
export default {
name: "Input",
props: {
inputType: {
type: String,
required: true,
default: "text",
},
inputName: {
type: String,
required: true,
},
fieldLabel: {
type: String,
required: true,
}
}
};
</script>
Home.vue
<template>
<div class="container is-max-desktop wrapper">
<div v-for="element in offer" :key="element.id">
<Input
v-model="element.fieldValue"
:value="element.fieldValue"
:fieldLabel="element.fieldLabel"
:inputType="element.fieldType"
:inputName="element.fieldName"
v-if="element.fieldType != 'select'"
class="mb-3"
/>
<Select
v-model="element.fieldValue"
:fieldLabel="element.fieldLabel"
:options="element.infoRequestFormOptions"
:selectName="element.fieldName"
v-if="element.fieldType == 'select'"
class="mb-3"
/>
</div>
<b-button type="is-danger" #click="getOffer()">GET</b-button>
</div>
</template>
<script>
import axios from "axios";
import Select from "../components/Select.vue";
import Input from "../components/Input.vue";
export default {
name: "Home",
data() {
return {
offer: [],
};
},
components: {
Select,
Input,
},
methods: {
getOfferForm() {
axios({
method: "get",
url: `/GETDYNAMICFORM`,
})
.then((response) => {
this.offer = response.data;
})
.catch(() => {
this.$buefy.toast.open({
duration: 3000,
message: "oops",
position: "is-bottom",
type: "is-danger",
});
});
},
getOffer() {
console.log(this.offer);
},
},
created() {
this.getOfferForm();
},
};
</script>
Example Dynamic Form Response like;
[
{
"id": 58,
"fieldLabel": "Name Surname",
"providerLabel": "Name Surname",
"fieldName": "nmsrnm",
"fieldType": "text",
"fieldValue": null,
},
{
"id": 60,
"fieldLabel": "E-mail",
"providerLabel": "E-mail",
"fieldName": "e_mail_60",
"fieldType": "email",
"fieldValue": null,
},
{
"id": 2,
"fieldLabel": "Budget",
"providerLabel": "Budget",
"fieldName": "bdget",
"fieldType": "select",
"fieldValue": "",
"infoRequestFormOptions": [
{
"id": 1,
"orderNum": 0,
"optionValue": 0,
"optionText": "Select",
"minValue": null,
"maxValue": null
},
{
"id": 2,
"orderNum": 1,
"optionValue": 1,
"optionText": "10-30",
"minValue": 10,
"maxValue": 30
}
]
}
]

vuex. Can't get access to object variable

look at my vuex code:
export default new Vuex.Store({
state: {
article: {},
slug: '',
},
actions: {
getArticleData(context, payload) {
axios.get('/api/article-json', { params: {slug:payload } }).then((response) =>{
context.commit('setArticleData', response.data.data);
});
}
},
getters: {
articleLikes(state) {
return state.article.statistic.likes;
},
articleViews(state) {
return state.article.statistic.views;
}
},
mutations: {
setArticleData(state, payload) {
state.article = payload;
},
setCurrentSlug(state, payload) {
state.slug = payload;
},
setCurrentStatistic(state, payload) {
state.statistic = payload;
}
}
})
the code works like this - getArticleData action set Data in article object.
In create() hook set article opbject:
{
"id": 14,
"title": "Deserunt ea natus pariatur sunt eum voluptatem.",
"img": "https://via.placeholder.com/600/5F113B/FFFFFF/?text=LARAVEL:8.*",
"body": " fugiat.",
"created_at": "1 месяц назад",
"comments": [
{
"id": 40,
"subject": "Impedit inventore quis.",
"body": "Qui rem ut beatae expedita nemo.",
"created_at": "2 дня назад"
},
{
"id": 41,
"subject": "Nam et sit.",
"body": "Dolor voluptas error eos quod.",
"created_at": "2 дня назад"
},
],
"tags": [
{
"id": 1,
"label": "Ut"
},
{
"id": 3,
"label": "Fugiat"
},
],
"statistic":
{
"likes": 7,
"views": 153
}
}
This object formed by Laravel resource
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'img' => $this->img,
'body' => $this->body,
'created_at' => $this->createdAtForHumans(),
'comments' => CommentResource::collection($this->whenLoaded('comments')),
'tags' => TagResource::collection($this->whenLoaded('tags')),
'statistic' => new StateResource($this->whenLoaded('state')),
];
}
I can't get access to article.statistic.views and article.statistic.likes from getters.
In views component i have code
computed: {
viewsNumber() {
return this.$store.getters.articleViews;
},
}
and template
<template>
<span class="badge bg-danger">{{viewsNumber}} <i class="far fa-eye"></i></span>
</template>
this is my console errors
app.js?id=80d6f0783c93a26b57e1:20787 [Vue warn]: Error in render: "TypeError: Cannot read property 'views' of undefined"
found in
---> <ViewsComponent> at resources/js/components/ViewsComponent.vue
<ArticleComponent> at resources/js/components/ArticleComponent.vue
<Root>
app.js?id=80d6f0783c93a26b57e1:22054 TypeError: Cannot read property 'views' of undefined
for comments and tags no problems. In comments component i have access to comments^
computed: {
article() {
return this.$store.state.article;
},
},
<div v-for="comment in article.comments">
<div class="toast showing" style="min-width: 100%;">
<div class="toast-body">
{{comment.body}}
</div>
</div>
</div>
What problem with article.statistic.likes and article.statistic.views?
The problem is it cannot verify whether views or likes will be available in articles.statistic.
You are not ensuring where articles.statistic will be defined or not.
So the simple solution is do a check before accessing any child element of articles.statistic
e.g. You can redefine your method like -
....
getters: {
articleLikes(state) {
if(state.article.statistic){
return state.article.statistic.likes;
} else {
return ...
}
},
articleViews(state) {
if(state.article.statistic){
return state.article.statistic.views;
} else {
return ...
}
}
},
....

DevExtreme - cell with FileUpload

Is there any possibility to create DataGrid cell with FileUpload associated with row.
For example I have database with records and I want to have a possibility to attach files to selected records.
Is someone know how to do that and can share with me ;)
Thanks a lot for your help :D
Do you mean something like this:
A simple demo:
<div class="demo-container">
<div id="gridContainer"></div>
</div>
<script>
$(function () {
var customers = [{
"ID": 1,
"CompanyName": "Premier Buy",
"Address": "7601 Penn Avenue South",
}, {
"ID": 2,
"CompanyName": "ElectrixMax",
"Address": "263 Shuman Blvd",
}, {
"ID": 3,
"CompanyName": "Video Emporium",
"Address": "1201 Elm Street",
}]
$("#gridContainer").dxDataGrid({
dataSource: customers,
showBorders: true,
columns: ["CompanyName", "Address", {
dataField: "COLUNIQID",
alignment: 'center',
caption: "Actions",
cellTemplate: function (container, options) {
$('<input type="file" />')
.on('change', function () {
//do the upload here
})
.appendTo(container);
}
}]
});
});
</script>

Vue - Clear true false toggles from out side a loop

I am relatively new to Vus.js and vanilla js, Im looking for some help. I have a loop where filters are toggled between false and true depending on the criteria. I have a button outside of all the vue loops that I would like to use to clear all the toggles - set all the data back to false.
I am using axios and a json file for my data. Theere are three filess I am working with filters.json, filters.js and the html
Thanks in advance for you help
json
[{
"name": "Category",
"filterVisible": false,
"buttonActive": false,
"values": [{
"name": "Single Cask",
"selected": false
},
{
"name": "Regional Malt",
"selected": false
},
{
"name": "New releases",
"selected": false
}
]
},
{
"name": "Region",
"filterVisible": false,
"buttonActive": false,
"values": [{
"name": "Highland",
"selected": false
},
{
"name": "Speyside",
"selected": false
},
{
"name": "Islay",
"selected": false
}
]
},
{
"name": "Brand",
"filterVisible": false,
"buttonActive": false,
"values": [{
"name": "Regional Malts",
"selected": false
},
{
"name": "Single Casks",
"selected": false
},
{
"name": "The Big Yin",
"selected": false
},
{
"name": "The Wee Yin",
"selected": false
}
]
},
{
"name": "Price",
"filterVisible": false,
"buttonActive": false,
"values": [{
"name": "£1-50",
"selected": false
},
{
"name": "£51-100",
"selected": false
}
]
}
]
fliters.js
var vm = new Vue({
el: '#app',
data: {
shopFilters: []
},
created() {
axios
.get(`shopFilters.json`)
.then(response => {
// JSON responses are automatically parsed.
this.shopFilters = response.data;
})
},
computed: {
}, // end computed
methods: {
// my attempt at clearing filter
clearAll: function(filter) {
shopFilters.filterVisible = false
}
}
});
html
<div class="shop__filter">
<div class="shop__filter-header">
<h6 class="shop__filter-heading"><img src="img/filter-symbol.png" />Filter</h6>
<p class="shop__filter-showing">showing 1-8 of 120</p>
**this is the bit I want to call the Function on**
<button #click="clearAll()" class="btn btn-white btn-mobile">clear filters</button>
</div>
<form>
<dl class="shop__filter-list">
<template v-for="filter in shopFilters">
<dt class="shop__filter-dt">
<button class="shop__btn-type"
v-on:click="filter.buttonActive = !filter.buttonActive"
:class="{'active' : filter.buttonActive}"
#click="toggle(filter)"
#click.self.prevent>
{{ filter.name }}
</button>
</dt>
<dd class="shop__filter-dd"
v-show="filter.filterVisible || option.selected"
:id="filter.name"
v-for="option in filter.values">
<button class="shop__btn-filter"
#click.self.prevent
v-on:click="option.selected = !option.selected"
:class="{'active' : option.selected}">
{{ option.name }}
</button>
</dd>
</template>
</dl>
</form>
</div>
I got a fix for this
clearAll: function() {
for (var i = 0; i < this.shopFilters.length; i++) {
var filter = this.shopFilters[i];
filter.buttonActive = false;
filter.filterVisible = false;
for (var j = 0; j < filter.values.length; j++) {
var option = filter.values[j];
option.selected = false;
}
}
}, // end clearAll