Vue component within code block, Vue attempting to render the template - vue.js

i'm trying to display example Vue component's within my documentation, however Vue is also recognizing the template within my Vue component.
vehicle-documents is not a registered component, and is also put into the following code:
Vue.config.ignoredElements = ['slide', 'slider', 'vehicle-documents'];
So Vue is ignoring the component itself:
If you want the modal make sure you add the click event and call the `open` function, and pass the `document` into this function call, as seen below.
```html
<vehicle-documents class="app" vehicle-id="">
<template v-slot:default="slotProps">
<button #click="slotProps.open(slotProps.document)">
{{ slotProps.document.name }}
</button>
</template>
</vehicle-documents>
```
How can I make Vue ignore the template block? I need Vue on this page, so it's not a simple case of just removing Vue.

Try this, add v-pre and type="text/x-template"
<vehicle-documents class="app" vehicle-id="">
<template v-pre type="text/x-template">
<button #click="slotProps.open(slotProps.document)">
{{ slotProps.document.name }}
</button>
</template>
</vehicle-documents>

Related

Vue3 Test error after the integration of vue-i18n

I integrated vue18n into my vue3 application. Everythings works fine but when I try to execute my unit tests (I'm using Jest) I have an error:
TypeError: Cannot read properties of undefined (reading 'deep')
As I wrote, I have errors only during the testing phase.
During my analysis I discovered that, probably, the issue it's related to a nested component.
I start the test from a component 'list', I trigger the click on a list item in order to show this 'popup' component.
In my test I initialize the component 'list' using mount instead of the shallowMount.
In this nested component "popup" I have this template:
<template>
<full-screen-popup ref="popup">
<div class="confirm-dialogue-container">
<div class="dialog-header">
<h1 id="confirm-title-lbl" v-t="titleKey"></h1>
<i18n-t :keypath="messageKey" tag="h2" id="confirm-message-lbl" scope="global">
<template v-slot:name>
<b id="confirm-name-lbl">{{name}}</b>
</template>
<template v-slot:surname>
<b id="confirm-surname-lbl">{{surname}}</b>
</template>
</i18n-t>
</div>
<div class="actions-container">
<button id="bt-confirm-delete" class="btn-action primary" v-t="confirmLblButton" #click="_confirm"></button>
<button id="bt-cancel-delete" class="btn-action " v-t="cancelLblButton" #click="_cancel"></button>
</div>
</div>
</full-screen-popup>
</template>
If I try to remove this content I don't have the error (obviously, I have other errors because the html dom will be empty).. but probably the issue it's related to this code.
I'm not able to understand the reason.
Any suggestions?

Vue slots props inside blade template

I have a Vue3 application that mounts on a blade/laravel. In one blade temlate, I have a Vue3 component (zest-dropzone) in which I insert a slot:
<template>
...
<slot name="hits" :button-label="buttonLabel" :files="files" :type="type" :state="state"></slot>
</template>
<script>
...
</script>
Inside the blade template, I have the following:
<zest-dropzone
accepted-files=".psd,application/pdf,audio/*,image/*,video/*"
button-label="{{ Lang::get('admin/button.edit') }}"
categories="{{ json_encode($categories) }}"
type="files">
<template #hits="hitsProps">
#{{ hitsProps.type }}
<zest-dropzone-files-preview :hitsProps="hitsProps" :button-label="buttonLabel" :files="files" :type="type" :state="state"></zest-dropzone-files-preview>
</template>
</zest-dropzone>
ZestDropzoneFilesPreview is another component which is registered globally and is technically rendered on the page, however the props are never coming no matter what I try.
Within the blade template, #{{ hitsProps.type }} renders correctly and the value type exists on hitsProps, however when I try to pass it in the next component, it doesn't come through and I get undefined inside ZestDropzoneFilesPreview.
Anyone knows how to deal with this? Thanks.
Fixed it, props were not passed accordingly (hitsProps -> hits-props).

How to use <slot/> as the root element of a Vue component?

I'd like to build a wrapper component, that just adds some JavaScript to the actual component that is passed in, but without creating an extra HTML element.
This works, but creates a div as the root element:
<template>
<div v-observe-visibility="{ callback: isViewableNow, once: true }"
:class="{ 'visible animated slideInRight': showAnimation, 'invisible': !showAnimation }">
<slot/>
<div/>
</template>
I'd like something similar, without adding the div, like:
<template>
<slot v-observe-visibility="{ callback: isViewableNow, once: true }"
:class="{ 'visible animated slideInRight': showAnimation, 'invisible': !showAnimation }"/>
</template>
This, however, gives me the error:
Cannot use as component root element because it may contain multiple nodes.
Is this possible in any other way in Vue?

v-if on a component template tag

From the docs:
Because v-if is a directive, it has to be attached to a single
element. But what if we want to toggle more than one element? In this
case we can use v-if on a element, which serves as an
invisible wrapper. The final rendered result will not include the
element.
But on my template in my component:
<template v-if="false">
<div>
....
</div>
</template>
But the component still renders.
I ask because I want a hook on the component so if v-if is true, I can do some code in beforeMounted and beforeDestroyed if false.
If I undestood what are you doing...
You're putting v-if int the template tag ina .vue file right?
Like this
// component.vue
<template v-if="false">
<div>
My Component
</div>
</template>
<script>
export default {
name: 'my-component'
};
</script>
<styles>
</styles>
Right?
If YES, you are doing it wrong.
The template there is a tag for Webpack Vue Loader to load the component template.
So the if must go inside the template tag.
// component.vue
<template>
<div v-if="false">
My Component
</div>
</template>
<script>
export default {
name: 'my-component'
};
</script>
<styles>
</styles>
If you need to "hide" multiple elements, just encapsulate into another div.
As Lucas Katayama said, you cannot use v-if inside SFC, but another way to hide you component is use v-if on this component in its parent component.
Your reference to the docs is correct, you can use a v-if on a template tag. However, I believe conditionals on the top-level <template> in a Single File Component are ignored.
To achieve the effect showed in the docs (conditional render a template) that template needs to be within the top-level template section.
Example:
<script>
// your script section
</script>
<template>
<template v-if="false">
<div>
....
</div>
</template>
</template>
<style>
// your style section
</style>

How do I use conditional rendering on template tag?

According to the Vue documentation I should be able to add the v-if condition to the <template> tag:
<template v-if="false">
<div>Invisible text</div>
</template>
But this will not hide the element, however it does work when added to the child element:
<template>
<div v-if="false">Invisible text</div>
</template>
Any suggestions?
I'm including the template in another .vue file:
<template>
<div id="app">
<H1 class= "main-title">Title</H1>
<span class="components">
<testtemplate></testtemplate>
</span>
</div>
</template>
The template tag of a single-file component is not rendered by Vue like normal <template> tags. It is simply one of the placeholders, along with <script> and <style> that vue-loader uses to build the component. The root element of that template is what will be the root in the component.
But, even if it worked the way you want, there would be no difference between your first and second example. Using v-if on the root will prevent the entire component's template from rendering if set to false.
Had this problem with VUE3. Using SFC just nest tag template inside another tag template :
<template>
<template v-if="false">
You won't see this
</template>
</template>