Vue Error: "the template root requires exactly one element" - html

I have the following components
component
<template>
<!--<post-form/>-->
<div class="wrapper">
<b-table :data="posts">
<template slot-scope="props">
<b-table-column field="completed" label="complete">
<b-checkbox
v-model="props.row.done">
</b-checkbox>
</b-table-column>
</template>
</b-table>
</div>
</template>
I have a b-table with buefy. And I want to import the <post-form /> component from the current component.
However, when I insert the component in the desired location, an error occurs.
<div class="wrapping"> If I place a component under it, my table is broken.
How can I solve this?

Maybe you are using Vue3, while you eslint config is still vue 2.
Try to edit your .eslintrc.json or something like this:
{
// ...
"extends": ["eslint:recommended", "plugin:vue/vue3-essential"],
// ...
}
Check out reference here: eslint-plugin-vue/#usage

We can only have one root element in the template. So, if you want to use as a sibling of div with class wrapper, you need to wrap both of these to a parent div, as below:
<template>
<div>
<post-form/>
<div class="wrapper">
<b-table :data="posts">
<template slot-scope="props">
<b-table-column field="completed" label="complete">
<b-checkbox
v-model="props.row.done">
</b-checkbox>
</b-table-column>
</template>
</b-table>
</div>
</div>
</template>

Related

How to insert template tag inside another template Vue.js

I'm trying to make a component that has a slot with a name attribute and another component with the same structure. So, I want to put the second component inside the first but in another outside component.
Example:
App.vue
<template>
<ComponentA>
<ComponentB>Hello World!</ComponentB>
</ComponentA>
</template>
ComponentA.vue
<template>
<div id="A">
<slot name="a1"></slot>
<slot name="a2"></slot>
</div>
</template>
ComponentB.vue
<template slot="a2">
<div id="B">
<slot></slot>
</div>
</template>
UPDATE!
codesandbox
If I write
<slot></slot>
instead of
<slot name='a2'></slot>
in ComponentA it will work. But I need use the last form, because I must control the order.

Named <slot> elements can't receive <template> elements

I have a little problem with the <slot/> element.
From Polymer version >= 1.8 <slot/> elements should be used, instead of <content/>, for creating insertion points. But a <slot/> cannot receive a <template/> element in any way, when it has a name.
When I create an unnamed (default) slot in my container element:
<dom-module id="my-container">
<template>
<slot id="defaultSlot"></slot>
</template>
</dom-module>
and nest a plain template:
<my-container id="container">
<template>
<div>foo</div>
</template>
</my-container>
it works perfectly, which can be verified using:
> container.$.defaultSlot.getDistributedNodes().length↵ -> 1
However, slotting of template elements stops working as soon as I give that slot a name:
<dom-module id="my-container">
<template>
<slot name="bar" id="namedSlot"></slot>
</template>
</dom-module>
<my-container id="container">
<template slot="bar">
<div>foo</div>
</template>
</my-container>
> container.$.namedSlot.getDistributedNodes().length↵ -> 0
What i really need is to make <slot/> somehow accept any <template/> by slot name.
Working Fiddle.

Polymer 1.0: Clickable item in dom-repeat to e.g. iron-page which contains further info (contact list)

I'm setting up a contact list in Polymer 1.0. When the user clicks on a name, there should be a (animated) page opened for further details. All of these data elements are pulled from an external .json file.
Two questions for this approach..:
1) where to begin? How do I wrap, for example, an iron-page or neon-animated-page around my current setup (which is searchable, which is also the -temporary- reason it's a dom-repeat instead of an iron-list):
<template id="resultlist" is="dom-repeat" items="{{data}}" filter="contactFilter">
<paper-item>
<paper-item-body two-line>
<div>{{item.name}}</div>
<div secondary>{{item.number}}</div>
</paper-item-body>
</paper-item>
</template>
2) For quick try-out with binding options I've created an paper-dialog (instead of an page behaviour) which displays further data for the chosen person... On top of that paper-dialog should the chosen name being displayed. But I only get the first name of the array in my .json file. How can I setup the code to display the {{item.name}} of the chosen item?
Ps. I'm aware of the contacts-app from Rob Dodson (https://github.com/robdodson/contacts-app), but I can't figure out how it should be done in Polymer 1.0.
Update 27.10.2015
After Hugo's answer I'm not able to get the solution to work in an dom-module structure.
Sorry for misunderstanding, but I can't figure out where I'm wrong.
Having to following:
phonebook.html, which acts like an index
...
<body unresolved>
<template is="dom-bind" id="application">
<neon-animated-pages selected="[[selected]]" entry-animation="fade-in-animation" exit-animation="fade-out-animation">
<contact-list></contact-list>
<contact-details></contact-details>
</neon-animated-pages>
</template>
<script>
var application = document.querySelector('#application');
application.selected = 0;
document.addEventListener('show-details', function() {
application.selected = 1;
});
document.addEventListener('show-list', function() {
application.selected = 0;
});
</script>
</body>
DOM-module contact-list.html, the list it self.
<dom-module id="contact-list">
<template>
<style include="phonebook-styles"></style>
<iron-ajax url="../data/data.json" handle-as="json" last-response="{{data}}" auto></iron-ajax>
<div class="container">
<h3>Contactlist:</h3>
<div class="template-container">
<template is="dom-repeat" id="templateUsers" items="{{data}}">
<paper-item on-tap="showDetails">
<paper-item-body two-line>
<div>{{item.name}}</div>
<div secondary>{{item.phonenumber}}</div>
</paper-item-body>
<div class="item-details-link">
<iron-icon icon="account-circle"></iron-icon>
</div>
</paper-item>
</template>
</div>
</div>
</template>
<script>
Polymer({
is: 'contact-list',
properties: {
selectedContact:{
type:Object,
value:function(){
return null;
}
}
},
showDetails: function(ev) {
var data = this.$.templateUsers.itemForElement(ev.target);
//alert(JSON.stringify(data)) // works with data chosen data selection...
this.selectedContact = data;
this.fire('show-details', this.selectedContact);
}
});
</script>
</dom-module>
DOM-module contact-details.html, the details-list.
<dom-module id="contact-details">
<template>
<!-- Do I need to declare the .json in my details module? -->
<iron-ajax url="../data/data.json" handle-as="json" last-response="{{data}}" auto></iron-ajax>
<paper-icon-button icon="arrow-back" on-tap="showList"></paper-icon-button>
<h3>Contact details</h3>
<template is="dom-repeat" items="{{data}}">
<div>{{selectedContact.name}}</div>
</template>
</template>
<script>
Polymer({
is: 'contact-details',
showList: function() {
this.fire('show-list');
}
});
</script>
</dom-module>
Everything, like the transitions, work. The chosen contact is also displayed in an alertbox (commented out in contact-list.html), but isn't forwarded to the contact-details.html page.
There are multiple steps to implement the solution:
Setup the neon animated pages ( one page would be the contact list, the other page would be the details )
Display the list of contacts ( you already have this one )
Add a "selectedContact" property to your element
Add a tap/click handler to the list items element and inside the handler set the selectedContact. You need to get the contact item from the DOM element clicked. ( Check an example here : http://jsbin.com/lofarabare/6/edit )
You can bind the contact details page elements to the selectedContact properties, e.g {{selectedContact.name}}
Inside the handler also Change the neon animated pages selected property to have it display the animation to the other page.
-- Extra feedback
I checked the way you handle events, feedback below:
Give the elements some id so you can add the event listener directly to them (e.g application.$.myContactList.addEventListener('show-detail',function(ev){...})
The way you fire the event from the contact-list is correct, however you are not reading the event data inside the event listener for the 'show-detail' event. The event listener receives the event as argument "ev". You can get the event data using ev.detail
With the event data (the selected contact) you can update your contact details component. Give it some id like 'details' and just update the 'selectedContact' property. **You need to declare the selectedContact in the details component, right now you don't have it there **

Conditional template on Polymer 1.0

I'm having trouble applying the new conditional template, in particular with the condition itself, I think.
I've got something like this:
<template is="dom-repeat" items="{{menuitems}}" as="poscol">
<template is="dom-if" if="{{index != 4}}">
<div class="positioncolum horizontal layout center wrap flex">
<span>{{index}}</span>
<template is="dom-repeat" items="{{poscol}}" as="mitem" >
<main-menu-item mitem="{{mitem}}"
order="{{mitem.TotalOrder}}"
onclick="clickMainMenuMod(index)">
</main-menu-item>
</template>
</div>
</template>
</template>
Now, if I comment the <template is="dom-if" if="{{index != 4}}"> bit it works fine, the index shows as it should.
On the fourth array are stored modules that the user has selected as non-visible, so they shouldn't appear on the main menu.
I guess there's something wrong with the if condition, but I can't guess what.
Thanks!
Try to modify your conditional template like this:
<template is="dom-if" if="{{show(index)}}">
And add this function to Polymer script:
show: function (index) {
return index != 4;
}

When I use Template Repeat how i know the Dom is ready

I using this template.
<template repeat = "{{cover in covers | keys}}">
<div class ='item'>
<img src="{{cover}}"></img>
</div>
</template>
and in my polymer script
domReady: function () {
//aplly some css
}
but when i debug the repeat is not over when the ready event is fired, so my css style changes is not happening.
It would be best to know what CSS you're trying add. Typically, you should not try to manage the DOM of a <template repeat> yourself. Instead, tweak it with your data model. For example, you could dynamically apply the "show" class to the image based on a property it sets:
<template repeat = "{{cover in covers | keys}}">
<div class ='item'>
<img src="{{cover}}" class="{{ {show: cover.show} | tokenList }}">
</div>
</template>
or do something similar by setting an inline style.