How to include external html in Nuxt app from object in js file with http url provided by bot constructor? - vue.js

I try to include a bot developed with landbot.io in my nuxt web app (NUXT.js framework).
Below, there is the code that the landbot's guide provides me.
Code to include:
<script src="https://static.landbot.io/landbot-widget/landbot-widget-1.0.0.js"></script>
<div id="myLandbot" style="width: 100%; height: 500px"></div>
<script>
var myLandbot = new LandbotFrameWidget({
container: '#myLandbot',
index: 'https://landbot.io/u/..../index.html',
});
</script>
But i don't know what i should do with the second script tag because i always get this error:
"LandbotFrameWidget do not definied"
I include the first script tag in nuxt.config.js like that:
head: {
script: [
{ src: 'https://static.landbot.io/umicore/UmiAccessPoint.js' },
{ src: 'https://static.landbot.io/landbot-widget/landbot-widget-1.0.0.js' }
]
}

Your nuxt.config.js config is correct, but the first script src is not needed.
I've created a working example in this codesandbox, take a look at the code used in the index.vue file:
<template>
<section>
<div>
<div id="myLandbot" style="width: 100vw; height: 100vh"></div>
</div>
</section>
</template>
<script>
export default {
mounted() {
var myLandbot = new LandbotFrameWidget({
container: "#myLandbot",
index: "https://landbot.io/u/H-117144-ZGUSSI5IM2OI5NYH/index.html"
});
}
};
</script>
Hope it helps!

Related

Set content of vue 3 single file components' style tag

I need to present some random/dynamic html data in my project that might contain style tags, by default vue.js doesn't allow style tags in the template to avoid messing styles that is a very good option.
To make my project work I tried some runtime-component projects on github but they doesn't accept css styles in the way I need, so I came up with the solution of creating my own runtime component with accepting css styles data.
What I want in code is sth like:
<template>
<div v-html="template"></div>
</template>
<script>
export default {
name: "DynamicTemplate",
props: {template: String, style: String}
}
</script>
<style scoped>
// style data goes here
</style>
Any alternative working solution is welcome too :)
I tried v-html and v-text attributes on the component style tag (without any results) and also using css #import statement with base64 encoded css codes (got some errors like Cannot read properties of undefined), but none of them worked :(
You can encapsulate the data inside the style tags inside the component tag provided by vue in this manner ->
<component :is="'style'"> .test-class { color: red; }....Your style data </component>
An example of the same can be found in this project I created
https://codesandbox.io/s/interesting-dewdney-id9erd?file=/src/components/HelloWorld.vue
Edit 1 =>
After reading the comment as I think the CSS scope compilation is done during the build process not during runtime thus having css at runtime won't scope it an alternate solution for this can be embedding your HTML code inside an iframe and passing your code to the iframe using the srcdoc attribute.An example of the same is given below
https://codesandbox.io/s/currying-cherry-zzv3wk?file=/src/components/HelloWorld.vue
<template>
<iframe style="width: 100vw; height: 80vh" :srcdoc="htmlCssCode"></iframe>
</template>
<script>
export default {
data() {
return {
htmlCssCode: `Your Html code here`
<html>
Here is an example of passing that can pass dynamic HTML data in your project with an example using style tags
<template>
<div>
<div v-html="template" :style="style"></div>
</div>
</template>
<script>
export default {
name: 'DynamicTemplate',
props: {
template: {
type: String,
required: true
},
style: {
type: Object,
required: false,
default: () => {}
}
}
}
</script>
Here is the component being used.
<DynamicTemplate
:template="<p>This is some dynamic HTML content</p>"
:style="{ color: 'red', font-size: '14px' }">
</DynamicTemplate>
Here is an example of passing that can pass dynamic HTML data in your project with an example of passing classes dynamically
<template>
<div>
<div v-html="template" :class="classes"></div>
</div>
</template>
<script>
export default {
name: 'DynamicTemplate',
props: {
template: {
type: String,
required: true
},
classes: {
type: Object,
required: false,
default: () => {}
}
}
}
</script>
Here is the component being used.
<DynamicTemplate
:template="template"
:classes="classes"
/>

Simple Nuxt 3 Page Transition not working

I'm discovering Nuxt 3 and and simply want to make an animation between pages. The idea is to use javascript hooks to make page transitions using js library such as gsap or animeJs.
So in my app.vue file, I simply put <NuxtPage/> into <Transition> element like this :
<NuxtLayout>
<Transition>
<NuxtPage/>
</Transition>
</NuxtLayout>
My vue pages ('./pages/index.vue' and './pages/project/myproject.vue') look like this :
<template>
<div>
<h1>My Project</h1>
</div>
</template>
<script setup>
function onEnter(el, done) {
done()
}
function onLeave(el, done) {
done()
}
</script>
I have followed both Nuxt 3 and Vue 3 documentations :
https://v3.nuxtjs.org/guide/directory-structure/pages#layouttransition-and-pagetransition
https://vuejs.org/guide/built-ins/transition.html#javascript-hooks
I also read this thread on github, but I can't find answer :
https://github.com/nuxt/framework/discussions/851
When i was using Nuxt 2 I only need to put transition object into my page like this and it's working fine :
<script>
export default {
// ... (datas, methods)
transition: {
mode: "in-out",
css: false,
enter(el, done) {
console.log("enter");
done()
},
leave(el, done) {
console.log("leave");
done()
}
}
}
</script>
<template>
<div>
<h1 class="text-center text-5xl">Hello World</h1>
</div>
</template>
Do you have any idea how to achieve it ?
Nuxt 3 doesn't need a <Transition> wrapper around pages/layouts, by default it does that for you.
Take a look at this starter template: in assets/sass/app.scss, the last part of the style is page and layout transition.
You can tweak the default named animations (page- and layout-).
More infos here
Just follow the official documentation for Nuxt 3. You need to add the following code to your nuxt.config.ts file:
export default defineNuxtConfig({
app: {
pageTransition: { name: 'page', mode: 'out-in' }
},
})
And then apply the classes inside your app.vue file, like this:
<template>
<NuxtPage />
</template>
<style>
.page-enter-active,
.page-leave-active {
transition: all 0.4s;
}
.page-enter-from,
.page-leave-to {
opacity: 0;
filter: blur(1rem);
}
</style>
Nuxt 3 uses the Vue's <Transition> component under the hood, so you don't need to add it in the template.
Be careful with the css prefix.

d3 graph rendering with vue

Because of non compatible dependencies, I have to downgrade from vue3 to vue2.
I have created a force directed graph with D3 library. Everything worked find with vue3 using composition api. I am not familiar with vue 2 and adapting my graph to vue2 has not been working out for me.
In vue3 it was very straitforward and ref() made it pretty easy to accomplish.
As for vue2, I have tried making good use of lifecycle hooks such as computed and watch
Any help is more than welcome
Here is a minimalistic representation of my working component in vue3. This component creates the graph in a svg and then renders it in the template.
<template>
<div class="col" style="position: absolute; width:100%; height:100%" >
<div class="main-map-container" style="overflow: hidden; width: 100%;">
<div ref="graph" class="canvas">
</div>
</div>
</div>
</template>
<script >
import {onMounted, onBeforeMount, ref} from 'vue'
export default {
setup(){
const graph = ref()
const links = [{src:"Amazon",target:"Aurora"},{src:"Amazon",target:"Aurora"},{src:"Amazon",target:"Zoox"},{src:"Amazon",target:"Rivian"}]
const nodes = [{id:"Amazon"},{id:"Aurora"},{id:"Zoox"},{id:"Rivian"}]
onBeforeMount( async ()=>{
const svgobj = ForceGraph(nodes, links)
graph.value.appendChild(svgobj);
})
function ForceGraph(
nodes,
links
){
// The code for the graph has been removed since it is much too long
return Object.assign( svg.node() );
}
return { graph }
}
}
</script>
<style></style>
This is the vue2 component that i have emptied for this post
<template>
<div class="col" style="position: absolute; width:100%; height:100%" >
<div class="main-map-container" style="overflow: hidden; width: 100%;">
<div ref="graph" class="canvas">
</div>
</div>
</div>
</template>
<script>
export default {
setup(){
},
methods: {
},
watch: {
},
props: {
},
computed: {
},
created() {
},
mounted() {
},
updated(){
},
data() {
return {
}}
}
</script>
<style>
</style>
You can use Vue3 composition API in vue 2. Install the composition api and then just keep your code the same, with the setup method exactly as it was.
The setup method, lifecycle hooks, and all the reactivity (refs and reactive objects) are made available to you, with very few incompatibilities.
We use d3 with Vue2 in this fashion all the time. 100% compatible.
https://github.com/vuejs/composition-api

Changing body styles in Nuxt/Vue template

I am trying to add body styles to my template in Nuxt, but I am running into issues.
I am trying to use the beforeCreate call, but when I do, I run into the error: document is not defined.
I would like to maintain SSR. How can I add styling on the body element?
<script scoped>
export default {
head() {
return {
script: [
{
src: '/js/vendor/jquery.min.js'
},
{
src: '/js/site.js'
}
]
}
},
beforeCreate: function() {
document.body.className = 'service';
}
}
</script>
<style scoped>
#import '~/assets/css/style.min.css';
</style>
Update
I added this:
head() {
return {
script: [
{
src: '/js/vendor/jquery.min.js'
},
{
src: '/js/site.js'
}
],
bodyAttrs: {
class: 'service',
}
}
}
The tag does get added to the body:
<body class="service" data-n-head="%7B%22class%22:%7B%22ssr%22:%22service%22%7D%7D" style="zoom: 1;">
However, the styling does not?
body.service{padding-top:80px}
body.service{font-family:'Geomanist', sans-serif;color:#000}
I think the best way handling this is using nuxt layouts (https://nuxtjs.org/docs/2.x/directory-structure/layouts/). Basically you can define your global html or body styles inside style secion of the layout file (which is also a vue file) and then use that layout with your pages (https://nuxtjs.org/docs/2.x/components-glossary/pages-layout/)
It seems you can add:
bodyAttrs: {
class: 'hidden',
},
in nuxt.config.js
According to this answer, you can create an app.html file at the root of your application with following content. I've added the class directly to the <body>:
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }} class="service">
{{ APP }}
</body>
</html>

GSAP implementing to Vue.js app with webpack

i have a problem with implementing GSAP to my vue.js app which i created with vue-cli and webpack
What i wanna do?
1- I tried to create tween beforeComponent mounting, in some function.
What i tried?
1- I create my vue app,
2- I already installed this package, with:
npm install greensock --save
everything is was okey with installation, then;
3- I imported TweenMax to main.js with this way:
import { TweenMax } from 'greensock';
4- I created some div into my component for animating with TweenMax.
5- I create some functions into methods of my component which wrapping the Tween,
methods: {
animate: function() {
TweenMax.to(".rect", 1, {x:100, alpha:0, ease:Sine.easeIn});
console.log('test');
}
},
and then i call this function on before mounting component;
beforeMount(){
this.animate()
}
so my tween not working, i'm not getting some error in my console.
I print the console.log("test"); for testing the function is work or not?.
result is function work. I'm getting the test message on console. But tween is no there :) .
Where i make mistake ?
Fully code of my component:
<template>
<div class="container">
<div class="home">
<h1>
HELLO
</h1>
<h4>
How are u doing?
</h4>
</div>
<div class="rect">
</div>
</div>
</template>
<script>
export default {
name: 'Home',
methods: {
animate: function() {
TweenMax.to(".rect", 1, {x:100, alpha:0, ease:Sine.easeIn});
console.log('test');
}
},
beforeMount(){
this.animate()
}
}
</script>
<style lang="scss">
.rect {
background-color:blue;
width: 10vw;
height: 100px;
position: absolute;
z-index: -1;
}
</style>
FIX . ///////////
While i wait to answer :) found the solution myself,
everything is fine with code, just need to call function not on beforeMount(), need to call it on mounted();