Load script inside the <template> tag using nuxt.js and vue.js - vue.js

I am using nuxt.js (which is based on vue.js) to build a custom website, I need to load an Ad on my website using a provided by my partners, and I need to place it at a specific place on my html code. So I add it to my component template but it does not render.
Here is a sample of the code I'm trying to get to work
<template>
<div>
<div class="columns is-centered is-mobile">
<p>Hello World</p>
</div>
<div>
<script type="text/javascript" src="sampleSource"></script>
</div>
</div>
</template>
<script>
export default {
}
</script>
the script that comes from src="sampleSource" doesn't load and doesn't execute, any help is appreciated. Thank you very much.

On the page, use in metadata with body: true for add script inside body
<script>
export default {
head: {
script: [
{ src: '/head.js' },
// Supported since Nuxt 1.0
{ src: '/body.js', body: true },
{ src: '/defer.js', defer: '' }
]
}
}
</script>

You need to create a (sample-source.vue) component and take it to the /components dir.
After that you need to create a plugin for your component: /plugins/sample-source.js
sample-source.js :
import Vue from 'vue'
import SampleSource from '~/components/sample-source.vue'
Vue.use(SampleSource)
nuxt.config.js:
...
module.export
...
plugins: [
'~/plugins/sample-source.js'
]
After these steps you can use your component everywhere.
Or the easiest way:
<template>
<div>
<div class="columns is-centered is-mobile">
<p>Hello World</p>
</div>
</div>
</template>
<script>
export default {
mounted () {
----your code here from sampleSource.js----
}
}
</script>

Related

Registering Vue components in html files

I'm having trouble using Vue.js components in HTML files.
Mainly I have a problem with registering the component and using it in the html file.
In general, I'd like to register a component and use it anywhere in the code. The current code that I took from the original Vue.js website works so that the component is added to the application right away.
index.html:
<body>
<div id="app">
<header></header>
<nav></nav>
<main></main>
<footer> </footer>
</div>
</body>
</html>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue#3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
import MyComponent from './header.js'
createApp(MyComponent).mount('#app')
</script>
Header.js:
export default {
data() {
return { count: 0 }
},
template: `<div>count is {{ count }}</div>`
}
Then the created component in another file actually works, but it is added automatically to the application.
How could I register this component and put it in the code where I want?

vue can't querySelector for child component DOM element

I cannot search for child component DOM element, my settings are as follows:
pages/Login.vue
<template>
<section class="login">
<div v-show="step === 4" class="login__container">
<Test />
</div>
</section>
</template>
<script>
export default {
data () {
return {
step: 1
}
},
async mounted () {
this.step = 4
await this.$nextTick()
document.querySelector('.test') // NULL
},
}
</script>
components/Test.vue
<template>
<div class="test">
foo
</div>
</template>
setTimeout of course is not solution. I also try the same on other page, but without success. What am I doing wrong? I guess the problem must be somewhere in the template or project configuration
#edit
i tried to do the same effect on jsfiddle vue template and fresh nuxt project but no problem there
You could try to use ref instead of querySelector to manipulate the component DOM :
<template>
<section class="login">
<div v-show="step === 4" class="login__container">
<Test ref="test"/>
</div>
</section>
</template>
<script>
export default {
data () {
return {
step: 1
}
},
mounted () {
this.step = 4
let test=this.$refs.test
},
}
</script>
Another way to access child component is emitting event when its ready and created in DOM,
In the child element:
<template>
<div ref="test">foo</div>
</template>
<script>
export default {
mounted() {
this.$emit('childMounted', this.$refs.test)
}
}
...
In your parent:
<template>
<section class="login">
<div v-show="step === 4" class="login__container">
<Test #childMounted="childMounted"/>
</div>
</section>
</template>
<script>
export default {
data () {
return {
step: 1
}
},
methods: {
childMounted(childRef) {
// Try here
// childRef: your child component reference
}
}
}
</script>
This kind of code should work properly
parent.vue
<template>
<div>
<test ref="parentTest" #hook:mounted="selectChildElement"></test>
</div>
</template>
<script>
export default {
methods: {
selectChildElement() {
console.log(this.$refs.parentTest.$refs.test)
},
},
}
</script>
Test.vue component
<template>
<div ref="test">foo</div>
</template>
This is because of the way the parent and children components are mounted, as explained here: https://stackoverflow.com/a/44319825/8816585
As Brahim said, it is also better to use $refs in an SPA context, more info available here.
The #hook:mounted trick was taken from this answer and initially found in this dev.to post.
As I thought, the problem is with nuxt, namely auto-importing components.
I am using automatic component import in the nuxt configuration.
nuxt.config.js
components: [
{
path: '~/components',
pathPrefix: false,
},
],
This approach apparently breaks something, and only after manually importing the component did it work properly
import Test from '#/components/Test.vue'
export default {
name: 'LoginPage',
components: {
Test
},
So the nuxt configuration caused the problem. Thank you for all your help.

Vue: can't use a component inside another compontent

I am trying to use a child compontent in another compontent and it does not work. I have been trying to solve this problem looking for typos etc. for hours, but can't find anything.
Menu.vue
<template>
<div class='navbar-and-alert'>
<alert/>
<nav class='navbar'>
</nav>
</div>
</template>
<script>
import Alert from './Alert.vue'
export default {
name: 'Navbar',
compontents: {
Alert
},
data (){
return {
}
},
}
</script>
Alert.vue
<template>
<section class='alert-section'>
<p class='alert-section__content'>
...
</p>
<a href=''><img src='/static/assets/img/close.svg' class='alert-section__close-icon'></a>
</section>
</template>
<script>
export default {
name: 'Alert',
}
</script>
I get this alert in console:
Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
The alert component works when used inside App.vue
components has a typo:
compontents: {
Alert
},
Should be:
components: {
Alert
},

Why won't vue.js update the DOM?

Working my way learning about Vue. I chose it as the better alternative after looking at React, Angular and Svelte.
I have a simple example that its not working probably because I'm not getting/understanding the reactive behaviour of Vue.
Plain simple App:
<template>
<div id="app">
<app-header></app-header>
<router-view />
<app-footer></app-footer>
</div>
</template>
<script>
import Header from './components/Header.vue'
import Home from './components/Home.vue'
import Footer from './components/Footer.vue'
export default {
components: {
name: 'App',
'app-header': Header,
'app-footer': Footer
}
}
</script>
Where Home.vue and Footer.vue have plain HTML content on the template.
On Header.vue I have:
<template>
<div>
<h1>The Header</h1>
<nav>
<ul>
<li>Curr Player: {{ ethaccount }}</li>
<li>Prop owner: {{ propOwner }}</li>
</ul>
</nav>
<hr />
</div>
</template>
<script>
export default {
data() {
return {
ethaccount: 'N/A',
propOwner: 'N/A'
}
},
methods: {
update() {
var ethaccount = '0xAAAAAA123456789123456789123456789'
console.log('ETH Account: ' + ethaccount)
var propOwner = '0xPPPPPPPPPPP987654321987654321'
console.log('Prop Account: ' + propOwner)
}
},
mounted() {
this.update()
}
}
</script>
But I'm unable to get the header updated and unable to find what I'm doing wrong. Help.
If you need to read a little bit more about the reactivity of the datas in vuejs check this link : https://v2.vuejs.org/v2/guide/reactivity.html
If you need to access/change your data try to do it like that :
this.$data.ethaccount = 'foo';
this.$data.propOwner = 'bar';
For me the problem is taht you re-declare your variable locally by doing :
var ethaccount = "0xAA...";
By doing such you never change the value of the data you're accessing through your template.
Hope it will solve your problem.

Vue js loading js file in mounted() hook

I have the following Vue component:
<template>
<div id="wrapper">
<div class="main-container">
<Header />
<router-view/>
<Footer/>
</div>
</div>
</template>
<script>
import './assets/js/popper.min.js';
// other imports
// ....
export default {
name: 'App',
components : {
Header,
Footer
},
mounted(){
// this is syntax error
import './assets/js/otherjsfile.js'
}
}
</script>
As is clear from the code snippet, I want to have the otherjsfile.js loaded in mounted() hook. That script file has certain IIFEs which expects the html of the web page to be fully loaded.
So how do I invoke that js file in a lifecycle hook?
This is the pattern I use. The example is importing a js file which contains an IIFY, which instantiates an object on window.
The only problem with this would occur if you want to use SSR, in which case you need Vue's <ClientOnly> component, see Browser API Access Restrictions
mounted() {
import('../public/myLibrary.js').then(m => {
// use my library here or call a method that uses it
});
},
Note it also works with npm installed libraries, with the same path conventions i.e non-relative path indicates the library is under node_modules.
I'm a little unsure of what your asking. But if you are just trying to include an external js file in your page, you can just use the script tag in your template and not have to put anything in your mounted function, like this:
<template>
<div id="wrapper">
<div class="main-container">
<Header />
<router-view/>
<Footer/>
</div>
<script src="./assets/js/otherjsfile.js"></script>
</div>
</template>
<script>
import './assets/js/popper.min.js';
// other imports
// ....
export default {
name: 'App',
components : {
Header,
Footer
},
}
</script>
Does this solve your issue?