Render a component in an iFrame - vue.js

I'm trying to render a Vue component within an iFrame but can't seem to get it to work. I've created a Vue widget that can be used on different websites but when using it on a website using Vuetify, the styles don't render correctly due to conflicts (my widget is using Vueitify which is what causes that problem).
My fallback therefore is to render the component in an iFrame.
This is what the App.vue file looks like. Ideally I want to encapsulate that parent div within an iFrame.
<template>
<div>
<!-- Production -->
<v-app v-if="env === 'production' && id" class="boodil-app">
<v-main>
<Payment :id="id"></Payment>
</v-main>
<!-- <router-view/> -->
</v-app>
<!-- Development -->
<v-app v-else-if="env === 'development'" class="boodil-app">
<v-main>
<Payment id="97155c9628574f30be5be7a21cb5c2c0"></Payment>
</v-main>
<!-- <router-view/> -->
</v-app>
</div>
</template>
<script>
import Payment from "#/views/Payment.vue";
export default {
props: ["id"],
components: {
Payment,
},
beforeMount() {},
data() {
return {
env: process.env.NODE_ENV,
};
},
};
</script>
<style>
.boodil-app > .v-application--wrap {
min-height: fit-content !important;
}
</style>

Related

vuejs transitions only on some views

I have transitions working between the pages of my vuejs application, defined in App.vue like so:
<template>
<div class="container mb-auto">
<router-view v-slot="{Component}" >
<transition name="slide" mode="out-in">
<component :is="Component" :key="route.path"></component>
</transition>
</router-view>
</div>
<TheFooter v-if="withMenu" />
</template>
// and definition of transitions in css
I don't want this to work between all views (pages) of my app, but only between views who's url starts with /welcome
How do I use some transitions between some pages, and other transitions between other pages?
You can use the JS transitions hooks as shown here: https://vuejs.org/guide/built-ins/transition.html#javascript-hooks
And make a check if you're on the correct path or not, example on a /welcome-home path below
<template>
<div>
<transition #before-enter="onBeforeEnter">
<!-- ... -->
</transition>
</div>
</template>
<script>
export default {
methods: {
onBeforeEnter() {
if (this.$route.path.startsWith('/welcome')) {
// cool transitions!
}
},
},
}
</script>

How can I wrap every v-if in my Vue code in a transition?

The task of having to write
<transition name="fade">
<div v-if="condition">
</div>
</transition>
Is manual labour. Is there any shortcut way of wrapping every v-if with a transition?
You can create a custom Vue component:
// AppTransition.vue
<template>
<transition name='fade'>
<div v-if='show'>
<slot />
</div>
</transition>
</template>
<script>
export default {
props: {
show: Boolean
}
}
</script>
and then use it as follows:
<template>
<AppTransition :show='condition'>
<div>Hello, world</div>
</AppTransition>
</template>
<script>
// You can avoid importing it everywhere by making it a global component, see https://vuejs.org/guide/components/registration.html
import AppTransition from './AppTransition'
export default {
components: { AppTransition }
}
</script>

NuxtPage vs slot for Nuxt3

What is the difference between these two components in Nuxt3 and how do I use them correctly?
If I want to use pages/... what is the right approach here to create links and jump from page to page?
Everything is pretty much explained in the documentation: https://v3.nuxtjs.org/migration/pages-and-layouts/
You need to use this in app.vue
<template>
<nuxt-layout>
<nuxt-page /> <!-- used to display the nested pages -->
</nuxt-layout>
</template>
With a default /layouts/default.vue file
<template>
<div>
this is coming from the layout
<slot /> <!-- required here only -->
</div>
</template>
You will get this on / (with /pages/index.vue)
<template>
<div>index page</div>
</template>
And with the following structure, you will achieve dynamic pages
/pages/users/index.vue
<script setup>
definePageMeta({
layout: false
});
function goToDynamicUser() {
return navigateTo({
name: 'users-id',
params: {
id: 23
}
})
}
</script>
<template>
<div>
<p>
index page
</p>
<button #click="goToDynamicUser">navigate to user 23</button>
</div>
</template>
/pages/users/[id].vue
<script setup>
definePageMeta({
layout: false
});
const route = useRoute()
</script>
<template>
<pre>{{ route.params.id }}</pre>
</template>
I've removed the layout here to show how to disable it, but you can totally let the default here or even provide a custom one.
So, nuxt-page is to be used when you want to display the pages in your app (replacing <nuxt /> and <nuxt-child />) while <slot /> is to be used in the layout (as any other component using the slot tag).

Nuxt.js - How to have separate layout?

In my default layout I have header and footer for every page. But in error pages I need a full page without header and footer. So I made another layout and I'm calling it in the export default section. But it's still have header and footer.
default.vue
<template>
<div>
<app-header></app-header>
<nuxt />
<app-footer></app-footer>
</div>
</template>
<script>
import Header from '~/components/Header.vue'
import Footer from '~/components/Footer.vue'
export default {
components: {
'app-header': Header,
'app-footer': Footer,
}
}
</script>
error.vue
<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<nuxt-link to="/">Home page</nuxt-link>
</div>
</template>
<script>
export default {
props: ['error'],
layout: 'fullpage' // you can set a custom layout for the error page
}
</script>
fullpage.vue
<template>
<div>
<nuxt />
</div>
</template>
Where I'm wrong?
You can do like this
1 - create a layouterror.vue file inside layouts folder (Put nothing inside just the basic code).
<template>
<div>
</div>
</template>
<script>
export default {}
</script>
<style>
</style>
2 - create a error.vue file inside layouts folder.
3 - and pass your error file a layout like this =>
export default {
layout: 'layouterror'
}
Maybe its help
Thanks !
ON Your Nuxt Project Folder called layouts, Create a file named error.vue and it will automatically detect all your 404 error which is page not found.
error.vue
<template>
<div class="error-page">
<h1>Oops, something went wrong!</h1>
<p>Back to safety!</p>
</div>
</template>
<style scoped>
.error-page {
text-align: center;
}
.error-page a {
text-decoration: none;
color: red;
}
.error-page a:hover,
.error-page a:active {
color: salmon;
}
</style>

Nesting a slot in a slot for vue

Update: Here's a simplified version of what I'm trying to achieve here (from the threaded conversation below):
Accept Component A - Accept Component B - Accept a condition - if
condition is true : wrap Component B with Component A [and render]- else only
render component B.
I'm interested in creating a component that renders a wrapper conditionally. I figured a theoretical approach like this would probably be best**:**
<template>
<div>
<slot v-if="wrapIf" name="wrapper">
<slot name="content"></slot>
</slot>
<slot v-else name="content"></slot>
</div>
</template>
<script>
export default {
props: {
wrapIf: Boolean,
}
}
</script>
Then when we implement, it would look something like this:
...
<wrapper-if :wrap-if="!!link">
<a :href="link" slot="wrapper"><slot></slot></a>
<template slot="content">
content
</template>
</wrapper-if>
The idea being that, in this case, if there is a link, then let's wrap the content with the wrapper slot (which can be any component/element). If there isn't, then let's just render the content without the wrapped link. Pretty simple logic, but it seems that I'm misunderstanding some basic vue functionality because this particular example does not work.
What is wrong with my code or is there some kind of native api that already achieves this or perhaps a dependency that does this sort of thing already?
The output should look like this:
wrapIf === true
<a href="some.link">
content
</a>
wrapIf === false
content
Just focus on the content itself, and let the component worry about whether or not to wrap the default or named content slot.
If you need the wrapper to be dynamic, a dynamic component should solve that. I've updated my solution accordingly. So if you need the wrapper to be a label element, just set the tag property to it, and so on and so forth.
const WrapperIf = Vue.extend({
template: `
<div>
<component :is="tag" v-if="wrapIf" class="wrapper">
<slot name="content"></slot>
</component>
<slot v-else name="content"></slot>
</div>
`,
props: ['wrapIf', 'tag']
});
new Vue({
el: '#app',
data() {
return {
link: 'https://stackoverflow.com/company',
tagList: ['p', 'label'],
tag: 'p',
wrap: true
}
},
components: {
WrapperIf
}
})
.wrapper {
display: block;
padding: 10px;
}
p.wrapper {
background-color: lightgray;
}
label.wrapper {
background-color: lavender;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<wrapper-if :wrap-if="wrap" :tag="tag">
<a :href="link" slot="content">
content
</a>
</wrapper-if>
<div>
Change wrapper type:
<select v-model="tag">
<option v-for="tag in tagList">{{tag}}</option>
</select>
</div>
<button #click="wrap = !wrap">Toggle wrapper</button>
</div>