Nuxt Failed to execute ‘appendChild’ on ‘Node’ when trying to get window size - vuejs2

The problem is that the project must be transferred to Nuxt and some of the code does not work. Namely, the size of the screen must perform actions with the text. Since Nuxt is an SSR, the code cannot be executed on the server side because it does not know the size of the window.
Can I somehow fulfill this idea so that everything works?
I have a project with nuxt and i18n
[nuxt] Error while initializing app DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
at Object.Je [as appendChild]
this my component vue
This code is an example of what causes an error.
<template>
<section>
<div>
<h2 class="subtitle" v-html="filterHeadSlogan"></h2>
</div>
</section>
</template>
<script>
export default {
name: 'testapp',
data() {
return {
filterHeadSlogan: '',
windowWidth: 0
}
},
methods: {
getWindowWidth(event) {
this.windowWidth = document.documentElement.clientWidth
var str = "<i>HELLO WORLD</i>"
if (this.windowWidth >= 960) {
this.filterHeadSlogan = str
} else {
this.filterHeadSlogan = str.replace(/<\/?[^>]+(>|$)/g, '')
}
}
},
mounted() {
this.$nextTick(function () {
window.addEventListener('resize', this.getWindowWidth);
//Init
this.getWindowWidth()
})
}
}
</script>

An error occurred because there was no data in the variable. The village appeared, but there was no data and there was a conflict. I created asyncData
async asyncData(){
return {
headSlogan: ""
}
},
Full code
<template>
<div class="westartslogan">
<div class="head-slogan">
<h2 v-html="headSlogan"></h2>
</div>
<h3>{{$t('page.home.wellcom_block_subtitle_left')}}</h3>
<ul>
<li><i class="icon"></i>
<div v-html="$t('page.home.wellcom_block_option_1_left')"></div></li>
<li><i class="icon"></i>
<div v-html="$t('page.home.wellcom_block_option_2_left')"></div></li>
<li><i class="icon"></i>
<div v-html="$t('page.home.wellcom_block_option_3_left')"></div></li>
<li><i class="icon"></i>
<div v-html="$t('page.home.wellcom_block_option_4_left')"></div></li>
<li><i class="icon"></i>
<div v-html="$t('page.home.wellcom_block_option_5_left')"></div></li>
</ul>
<div class="startcalc-btn button-container">
<nuxt-link :to="getLocalizedRoute({ name: 'calculator' })" class="uk-button uk-button-default">{{
$t('page.home.wellcom_button_calculator') }}
</nuxt-link >
</div>
<div class="ourproject-btn uk-hidden#s">
<div class="button-container">
<nuxt-link :to="getLocalizedRoute({ name: 'portfolio' })" class="uk-button uk-button-default">
{{ $t('page.home.wellcom_button_portfolio') }}
</nuxt-link>
</div>
</div>
</div>
</template>
<script>
export default {
async asyncData(){
return {
headSlogan: ""
}
},
name: 'we_can',
data () {
return {
filterHeadSlogan: '',
headSlogan: this.$i18n.t('page.home.wellcom_block_title_left'),
windowWidth: 0
}
},
methods: {
getWindowWidth (event) {
this.windowWidth = document.documentElement.clientWidth
if (this.windowWidth >= 960) {
this.headSlogan = this.headSlogan
} else {
var str = this.headSlogan
this.headSlogan = str.replace(/<\/?[^>]+(>|$)/g, '')
}
}
},
mounted() {
this.$nextTick(function () {
window.addEventListener('resize', this.getWindowWidth);
//Init
this.getWindowWidth()
})
}
}
</script>
<style scoped>
</style>

I was dealing with the same problem.
Do these steps:
Run your project (yarn start).
Open http://localhost:3000/ in Chrome.
In Chrome devtools clear site data in application tab.
Hard reload the page.

Related

How can I resolve this error when calling v-for?

basically my error is that when I run npm run build on the project it points out that it can't find my manuals list
**npm error:
npm run build
vue-tsc --noEmit && vite build
src/views/ManuaisView.vue:11:80 - error TS2304: Cannot find name 'manuais'.
11 **
Found 1 error.
Code:
<div class="flex flex-wrap -mx-4">
<div class="w-full md:w-1/2 lg:w-1/3 px-4" v-for="(manual, idx) in manuais" :key="manual.key">
<div class="h-full p-8 text-center hover:bg-white rounded-md hover:shadow-xl transition duration-200">
<div class="inline-flex h-16 w-16 mb-6 mx-auto items-center justify-center text-white bg-vermelho rounded-lg">
<i class="far fa-file-pdf fa-2x"></i>
</div>
<h3 class="mb-4 text-xl md:text-2xl leading-tight font-bold">{{manual.nome}}</h3>
<p>{{manual.descritivo}}</p>
<p>{{manual.link}}</p>
</div>
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { meudb } from '../db';
var post:any = [];
var items: any;
const postRef = meudb.ref('********').once('value', (snapshot) => {
const documents = snapshot.val();
snapshot.forEach(d => {
post.push({nome:d.val().nome, descritivo:d.val().descritivo, link:d.val().nivel})
});
items = documents
console.log(post);
// do something with documents
});
console.log(postRef);
export default {
data() {
return {
manuais: post,
// manuais: [],
}
},
firebase: {
manuais: {
source: meudb.ref('********'),
asObject: true
}
}
}
</script>
If you want to update the manuais value you should set it to an empty array in its definition (in the data) and update its value in the mounted lifecycle (check documentation here
Example :
export default {
data: () => {
return {
manuais: [],
}
},
mounted() {
var post: any = [];
var items: any;
const postRef = meudb.ref('********').once('value', (snapshot) => {
const documents = snapshot.val();
snapshot.forEach(d => {
post.push({
nome: d.val().nome,
descritivo: d.val().descritivo,
link: d.val().nivel
})
});
items = documents
// do something with documents
});
this.manuais = post; // <-- here updating the value
}
}
Working snippet
Here is a little snippet for you to better undestand how works v for.
In your case, if you apply this logic, your code might work
new Vue({
el: '#app',
data: () => ({
manuais: []
}),
mounted() {
// get data from dataBase here
this.manuais = [{
name: 'foo'
}, {
name: 'bar'
}]
}
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<div id="app">
<div v-for="manual in manuals">{{ manual.name }}</div>
</div>

can't display vuejs data property inside vue template

I'm trying to use eventbus to send data from component A:
<template>
<div v-for="(user, index) in users" :key="index" class="col-lg-6">
<div class="card card-primary card-outline">
<div class="card-body d-flex">
<h1 class="mr-auto">{{ user.name }}</h1>
Afficher
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
users: {},
}
},
methods: {
envoyerDetails($data){
Fire.$emit('envoyer_details_projet', $data);
this.$router.push('details-projet');
},
loadUser() {
if(this.$gate.isAdmin()){
axios.get("api/user").then(({ data }) => (this.users = data.data));
}
}
},
mounted() {
this.loadUser()
}
}
</script>
In component B, i receive the data and i want to display it inside the template this way:
<template>
<div class="right_col text-center" role="main">
<h5><b>name: {{ user.name }}</b> </h5>
</div>
</template>
export default {
data() {
return {
user: {},
}
},
methods: {
afficherDetails (args) {
this.user = args;
console.log(this.user.name);
}
},
mounted() {
Fire.$on('envoyer_details_projet', this.afficheDetails);
}
}
The data is not displayed in the template but it is displayed in the console. What am i missing?
Maybe when you emit the event envoyer_details_projet in component A, but component B is not mounted yet so that it can't receive the data.

why beforeRouteUpdate is not updating route

I am showing the products page use vueJS and API.
I am showing categories on the left side and products on the right side
but while clicking on category products should be shown and the same component should be a load but the same component is not loading
Please check why beforeRouteUpdate is not working
below is my code
<template>
<div style="padding: 25px">
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="row">
<h3>Categories</h3>
<div class="col-md-12" align="left">
<router-link type="button" align="left" class="card-link" :to="'/'">
All Products</router-link>
</div>
<div class="col-md-12" v-for="category in categories" :key="category.id">
<CategoryCard :category="category" />
</div>
</div>
</div>
<div class="col-md-9">
<h1 class="index-msg">
{{ msg }}
</h1>
<div v-if="isShowId">
<span>props id:{{id}}</span>
<br />
<span>route.params id: {{uid}}</span>
</div>
<div class="row">
<div class="col-md-4" v-for="product in products" :key="product.id">
<ProductCard :product="product" />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
mapActions,
mapGetters
} from "vuex";
import CategoryCard from "../../components/products/CategoryCard";
import ProductCard from "../../components/products/ProductCard";
export default {
name: "Products",
props: ["id"],
computed: {
...mapGetters("product", ["products"]),
...mapGetters("category", ["categories"]),
},
components: {
ProductCard,
CategoryCard,
},
data() {
return {
msg: "Products Page",
uid: "",
isShowId: false,
};
},
methods: {
...mapActions("product", ["getProducts", "addCart", "removeCart"]),
...mapActions("category", ["getCategories"]),
},
mounted() {
let id = this.$route.params.id;
if (id) {
this.isShowId = true;
this.uid = id;
} else {
this.isShowId = false;
this.uid = "";
}
this.getProducts(id);
this.getCategories();
},
beforeRouteUpdate (to, from, next) {
next();
},
beforeRouteLeave (to, from, next) {
console.log(`Leave to =`, to);
console.log(`Leave from =`, from);
next();
},
};
</script>
Try to check what's the 'pathPre' variable here. This will help you finding where to route now.
beforeRouteUpdate: function (to, from, next) {
let pathPre = from.path.split("/");
console.log(pathPre)
next();
},
And if you want to just reload the route on the same url then use
this.$router.go();
Edited
Load with variable as slug
Try to use slug with route
{
path: '/routeA/:slug',
name: 'routeName',
component: routeA,
props:true,
}
and push to url with slug and route name
this.$router.push({
name: "routeName",
params: { slug: passSlugVariable },
});
and catch this prop in data as variable
data: function () {
return {
slug: this.$route.params.slug,
};
}
watch: {
'$route'(to, from) {
let to_path = to.path;
let from_path = from.path;
console.log(`to =`, to_path);
console.log(`from =`, from_path);
if (to_path !== from_path) {
this.$router.push(to_path)
this.$router.go();
} else {
this.$router.go();
}
},
},
This is working as I am refreshing the page every time using this.$router.go(); , I know this is wrong method , please tell me correct solution

Why is object not defined?

I want to try Vue.js 2 and started with a simple example. I've took this one from here https://jsfiddle.net/gmsa/gfg30Lgv/ and created a simple project with it. After I divided this code into files the project doesn't work. So I've made a data property a function:
data: function(){
return {
tabs: [{
name: "tab1",
id : 0,
isActive: true
}],
activeTab: {}
}
},
But there's an error in a console: Uncaught ReferenceError: newTab is not defined.
Project: https://github.com/rinatoptimus/vue-webpack-delete
File QueryBrowserContainer:
<template>
<div id="queryBrowserContainer">
<p>queryBrowserContainer text</p>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" v-for="tab in tabs" :class="{active:tab.isActive}">
{{ tab.name }}
</li>
<li>
<button type="button" class="btn btn-primary" #click="openNewTab">New tab</button>
</li>
</ul>
<div class="tab-content">
<div v-for="tab in tabs" role="tabpanel" class="tab-pane" :class="{active:tab.isActive}">
<app-querybrowsertab :tab="tab"></app-querybrowsertab>
</div>
</div>
<pre>{{ $data | json }}</pre>
</div>
</template>
<script>
import QueryBrowserTab from './QueryBrowserTab.vue';
export default {
data: function(){
return {
tabs: [{
name: "tab1",
id : 0,
isActive: true
}],
activeTab: {}
}
},
ready: function () {
this.setActive(this.tabs[0]);
},
methods: {
setActive: function (tab) {
var self = this;
tab.isActive = true;
this.activeTab = tab;
/*this.activeTab.isActive = true;
console.log("activeTab name=" + this.activeTab.name);*/
this.tabs.forEach(function (tab) {
if (tab.id !== self.activeTab.id) { tab.isActive = false;}
});
},
openNewTab: function () {
newTab = {
name: "tab" + (this.tabs.length + 1),
id: this.tabs.length,
isActive: true
};
this.tabs.push(newTab);
this.setActive(newTab);
/*this.activeTab = newTab;
console.log("### newtab name=" + newTab.name);*/
},
test: function() {
alert('676767');
},
closeTab: function () {
console.log("### CLOSE!");
}
}
}
File QueryBrowserTab:
<template>
<div>
<p>querybbbTab</p>
<h3>{{tab.name}}</h3>
<h3>{{tab.id}}</h3>
</div>
</template>
<script>
import QueryBrowserContainer from './QueryBrowserContainer.vue';
export default {
data: function () {
return {
databaseOptions: [],
};
},
props: ['tab'],
methods: {},
components: {
'app-querybrowsercontainer': QueryBrowserContainer
}
}
</script>
File App:
<template>
<div id="app">
<app-message></app-message>
<app-querybrowsertab></app-querybrowsertab>
<app-querybrowsercontainer></app-querybrowsercontainer>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {}
}
}
</script>
It seems in file: QueryBrowserTab, you have not passed tab props, but you are using it, make sure you pass tab as props from whatever places you are using it.
As stated in the docs here, you can pass props to a component like following:
<app-querybrowsertab :tab="tab"></app-querybrowsertab>
which you are already doing in app-querybrowsercontainer,but in file App, you are not passing the prop, which might be the source of error for you.

Returning promise from api and putting into global data

Sorry if this is obvious but new to vue and my js not so great.....
I'm trying to get some data from an api and then put that data into a global object so it can be passed down to some child components.
I can't seem to $set the data into the global projects object, it either returns undefined or returns a promise.
parent --
<template>
<div id="app">
<section class="intro">
<h1>WELCOME</h1>
</section>
<transition name="fade"> <router-view class="view" :computedProjects=computedProject ></router-view></transition>
</div>
</template>
<script>
import projectsList from './components/projectsList'
var client = contentful.createClient({
// This is the space ID. A space is like a project folder in Contentful terms
space: '',
// This is the access token for this space. Normally you get both ID and the token in the Contentful web app
accessToken: '',
})
var PRODUCT_CONTENT_TYPE_ID = 'project'
export default {
name: 'app',
components: {
projectsList
},
data: function() {
return {
users:'',
projects:'',
}
},
methods: {},
created : function () {
client.getEntries().then((response) => {
console.log(response)
this.projects = response
console.log(this.projects)
return response
});
},
computed: {
computedProject: function() {
if (!this.projects) return null;
return this.projects;
}
}
}
}
child ---
<template>
<section class="project-list">
<swiper :options="swiperOption">
<swiper-slide v-for="project in projects" v-bind:ref="'project' + project.name" :key="project.name" data-swiper-parallax="-100">
<div class="project-cover wrapper">
{{project.name}}
<router-link :to="{ name: 'project', params: { id: project.name }}">
<div class="cover-img" :style="{ 'background-image': 'url(../static/img/projects/'+project.name+'/'+'project-details-header.jpg)' }"> </div>
<div class="project-copy"></div>
<div href="#" class="tilter tilter--4">
<figure class="tilter__figure">
<img class="tilter__image" :src="'+project.fields.coverImage.fields.file.url+'" alt="" />
<div class="tilter__deco tilter__deco--shine"></div>
<div class="tilter__deco tilter__deco--overlay" v-bind:style="{ backgroundImage: project.gradient }"></div>
<figcaption class="tilter__caption">
<h1 class="projectName tilter__title title">{{project.name}}</h1>
<h2 class="tilter__description">{{project.tagline}}</h2>
</figcaption>
<svg class="tilter__deco tilter__deco--lines" viewBox="0 0 300 415">
<path d="M20.5,20.5h260v375h-260V20.5z" />
</svg>
</figure>
</div>
</router-link>
</div>
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</section>
</template>
<script>
export default {
data: function () {
return {
swiperOption: {
autoplay:false,
setWrapperSize :true,
observeParents:true,
keyboardControl : true,
centeredSlides :true,
freeMode:false,
freeModeSticky:true,
pagination: '.swiper-pagination',
paginationType: 'progress',
watchSlidesProgress : true,
watchSlidesVisibility : true,
speed:650,
grabCursor:true,
parallax:true
},
}
},
props :['computedProject'],
created : function () {
console.log(this.projects)
},
any help will be appreciated.
You can just assign the vue data variable in the callback of getEntries like following:
created : function () {
var self = this
client.getEntries().then((response) => {
console.log(response)
self.projects = response
})
console.log(this.projects)
},