How do you get a custom element to load using Aurelia - aurelia

I have a custom element like the nav-bar in the skeleton-navigation except I am not using the router part. I can't seem to get it to fire any events.
Code:
nav-bar.html
<template>
<ul id="topMenu"></ul>
</template>
nav-bar.js
attached() {
alert('test')
}
Containing page:
<template>
<require from="./nav-bar.html"></require>
<div class="desktop" id="container">
<nav-bar></nav-bar>
</div>
</template>

When you load the custom element using .html at the end of the path, Aurelia does not load the .js file. Just change your require element to the following, and it will work as you expect:
<require from="./nav-bar"></require>

Related

The client-side rendered virtual DOM tree is not matching server-rendered content

Versions
nuxt: ^2.14.12
node: v14.15.4
Reproduction
Hello everyone and thank you in advance.
I have a strange issue that I don't really understand what's the problem and how to deal with it.
I have installed a fresh nuxt ssr project.
I'm getting the following warning
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
I have three simple components: Form, Input, Button.
Form.vue
<template>
<form v-bind="$attrs" class="w-full" #submit.prevent="$emit('submitted')">
<div class="space-y-2 mb-4">
<slot name="fields" />
</div>
<slot name="button" />
</div>
</form>
</template>
<script>
export default {
computed: {
hasFields() {
return !!this.$slots.fields
},
},
}
</script>
Input.vue
<template>
<div class="relative w-full">
<input class="form-input block w-full" />
</div>
</template>
<script>
export default {
inheritAttrs: false,
}
</script>
Button.vue
<template>
<button
type="submit"
class="relative btn inline-flex items-center justify-center transition ease-in-out duration-150"
>
Save
</button>
</template>
<script>
export default {}
</script>
I use my components in pages/index.vue like this:
<template>
<div>
<Form>
<template #fields>
<Input />
<Input />
</template>
<template #button>
<Button />
</template>
</Form>
<Form>
<template #fields>
<Input />
<Input />
</template>
<template #button>
<Button />
</template>
</Form>
</div>
</template>
<script>
export default {}
</script>
If i use the Form component only once in the view i don't get the warning.
If i use it twice i get it.
Steps to reproduce
Reproduction link
Install a fresh nuxt ssr project.
Create the components as in the reproduction link
What is Expected?
All the components to render normally without any warnings or errors.
What is actually happening?
I get the following warning.
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
Some extra notes
I know that wrapping the whole thing inside a <client-only> fixes the problem but i want to understand why is this happening in order to avoid it in future cases.
Also if I remove components: true from nuxt.config.js and import the components normally again the warning is gone.
Changing the name of the components eg Button -> TheButton won't fix the problem. You can see the reproduction here.
<script>
import Input from '~/components/Input'
import Button from '~/components/Button'
import Form from '~/components/Form'
export default {
components: { Form, Button, Input}
}
</script>
There seems to be one or more components which are not supported in "Universal" Mode, i.e. they might have code which isn't being executed correctly on server end.
Please try finding that component which you think can cause an issue and wrap that component with .
Here's the link for more information: https://nuxtjs.org/docs/2.x/features/nuxt-components#the-client-only-component

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>

Vue.js can template without no root element or vue el specify for two div

HTML:
<div class="a">
Some HTML ...
</div>
<div class="b">
Some HTML
</div>
Javascript:
new Vue({
el: "#item_info",
....
....
(Other Config)
....
....
})
The two div above need to show the information from vue,
I tried using <template></template> like:
<template>
(my two div)
</template>
but it does not work because both divs need to be inside a root element.
I know that if I modify my html to:
<div id="item_info">
<div class="a"></div>
<div class="b"></div>
</div>
It can work, but I have no authorization to modify the base Html structure
Is there any other way that could help me solve it?
Maybe you should try to split those div's in two components and then add them to parent.
One.vue
<template>
<div class="a">
Some HTML ...
</div>
</template>
Two.vue
<template>
<div class="b">
Some HTML
</div>
</template>
Three.vue
<template>
<One></One>
<Two></Two>
</template>
If you have no authorization then I think you can't put that <template></template> either. Vue JS doesn't allow selecting multiple elements. But you can use Vue Component, please refer to this official link of Vue JS: https://v2.vuejs.org/v2/guide/components.html.
But remember Component also requires one root element.

Aurelia router-view inside dialog not working on reopening dialog

As per example given in aurelia documentation I am opening dialog box with viewmodel (say prompt ). This prompt has view inside in which I am adding "router-view" tag.
My routes are already configured. So when first time I open dialog it opens correct views as configured in routes and everything works well. But when I close dialog and re-opens dialog, It's not showing first route view. If I click other route link and come back to first route it works.
I have observed it's not creating instance of view model of first route( when opened dialog second time).
How to fix this issue?
Prompt html
<template><div class="row">
<left-menu ></left-menu>
<router-view></router-view>
</div></template>
<template>
and left-menu.htm
<template>
<div class="list-group">
<template repeat.for="item of items">
<a class="list-group-item ${$parent.selectedNav === item.routeName ? 'active' : ''}" route-href="route.bind: item.routeName;" click.delegate="$parent.select(item)">${item.text}</a>
</template>
</div>
Using a router inside a modal window seems off to me. The router is used to manage pages, but a modal is used to manage content within a page.
I would suggest building a modal window component, you can use <slot> tags to inject content and set it's model bindings to any data within the current view model.
Here's an example of my component that I use for this.
<template>
<div show.bind="visibility" class="modal-window">
<div>
<button class="btn btn-danger btn-sm close-button" click.delegate="close()">close</button>
</div>
<slot></slot>
</div>
<div show.bind="visibility" class="modal-window-overlay" click.delegate="close()"></div>
</template>
-
import { bindable } from 'aurelia-framework';
export class ModalContent {
#bindable visibility: boolean;
close(){
this.visibility = false;
}
}
<modal-content id.bind="'add-variant-window'">
<h4>Modal Content</h4>
<div>you can bind this to things on the current viewmodel</div>
</modal-content>