I am trying to bind a dictionary of attributes like {'id': 'myid', 'class': 'my-1 pr-md-2', ...}
at the time I am defining the element. I do not want to set that attributes after the DOM is loaded by Javascript.
I am struggling with the correct form of doing this. I can not bind them one by one declaring the attribute name and value manually as they are user given parameters. I have think of appending them to the attributes
property, but I do not know if it is advisable to do it this way.
This is my data structure:
<template is="dom-repeat" items="{{links}}" as="link">
<a class="nav-item nav-link mr-md-2" on-tap="changePage">{{link.title}}</a>
</template>
and the attributes are saved in each link.attributes
property. My solution would be something like this:
HTML
<template is="dom-repeat" items="{{links}}" as="link">
<a attributes={{appendAttributes(link)}} class="nav-item nav-link mr-md-2" on-tap="changePage">{{link.title}}</a>
</template>
JS
appendAttributes: function(link){
//Get current attributes of the element and append the ones in link.attributes
}
Is this the correct way to handle it?
As far as I know this is not possible with Polymer's templating system: there's no way to access the element to which a computed binding is applied to.
This
<a attributes={{appendAttributes(link)}}></a>
can't work because the attributes
property is read-only.
I can not bind them one by one declaring the attribute name and value manually as they are user given parameters
Actually if you know in advance what attributes/properties have to be set you can still set them dynamically:
<a id=[[userGivenId]]
class$=[[userGivenClass]]
...
></a>
Anyway, there is a lit-html
directive made by open-wc
called spread which does just what you want. This would require rewriting your component using LitElement to something like this:
import { LitElement, html, property, customElement } from 'lit-element';
import { repeat } from 'lit-html/directives/repeat';
import { spread } from '@open-wc/lit-helpers';
@customElement('my-element')
export class MyElement extends LitElement {
@property() userGivenId;
@property() links;
// ...
render() {
return html`
${repeat(this.links, link => html`
<a ...=${spread({
id: this.userGivenId,
'?my-boolean-attribute': true
'.myProperty': { foo: 'bar' },
'@my-event': () => console.log('my-event fired'),
})}
class="nav-item nav-link mr-md-2"
@click=${e => this.changePage(e)}
>${link.title}</a>
`)}
`;
}
}
With some limitations, PolymerElement
s and LitElement
s can coexist in the same project so converting a single component shouldn't cause any trouble.