Use properties or slot for pass data to child element

6.3k Views Asked by At

I've a question about what it is the best way to pass some value from a father component to a child component and show the value, because I've tried to pass value with properties and slot and both ways work. Properties: I've a movement list and use repeat from lit-html (and method html to render) in the father component in order to create n child component giving the values in them properties.

//father component
render(){
    return html`
        ${repeat(movements, movement => movement.id, (movement, index)=> html`
            <movement
            .id=${movement.id} .description=${movement.description} .amount=${movement.amount} .balance=${movement.balance}>
            </movement>
            <hr>
        `)}
    `    
}

//child component
render(){
    return html`
        <dt>${this.id}</dt>
        <dl>${this.description}</dl>
        <dl>${this.amount}</dl>
        <dl>${this.balance}</dl>
    `;
}

Slot: I've a movement list and use repeat from lit-html (and method html to render) in the father component in order to create n child component giving the values in slot which were declared in the child component

//child component
render(){
    return html`
    <dd>
        <slot name="id"></slot>
        <slot name="description"></slot>
        <slot name="amount"></slot>
        <slot name="balance"></slot>
    </dd>
    `;
}

//father component
render(){
    return html`
        ${repeat(movements, movement=>movement.id, (movement, index)=>html`
            <movement>
                <dt slot="id"> ${movement.id} </dt>
                <dl slot="description"> ${movement.description} </dl>
                <dl slot="amount"> ${movement.amount} </dl>
                <dl slot="balance"> ${movement.balance} </dl>
            </movement>
        `)}
    `;
}

Which it is the best way? When do I have to use one and the other?

4

There are 4 best solutions below

0
On

Here is an example to pass of object's properties with using LitElement:

DEMO

import { LitElement, html } from '@polymer/lit-element'; 

class MyElement extends LitElement {

  static get properties() { return { 
    movements: {
        type:Object 
      }
    }
  }

  constructor(){
    super();
    // Initialize property here.
      this.movements = [{id:"123", amount:40000, description:"Bu yuzyilin en buyuk lideri Atatürk tür", balance:20000},{id:"123", amount:40000, description:"Tosun was here ! :) ", balance:20000},{id:"123", amount:40000, description:"Ne Mutlu Diyene, Buraarda ırkçı olmayahh :)) ", balance:20000}];
  }

 //father component
render(){
  return html`
         ${this.movements.map(movement => html`<movement-list  .id=${movement.id} .description=${movement.description} .amount=${movement.amount} .balance=${movement.balance}></movement-list>`)}

  `;
}
}

class MovementList extends LitElement {

  static get properties() { return { 
    id: {type:String},
    description: {type:String},
    amount: {type:Number},
    balance: {type:Number}
    }
  }
  //child component
render(){
    return html`
        <dt>${this.id}</dt>
        <dl>${this.description}</dl>
        <dl>${this.amount}</dl>
        <dl>${this.balance}</dl> 

    `;
}

}
customElements.define('my-element', MyElement);
customElements.define('movement-list', MovementList);
0
On

This is another way to pass property.

If you are using slots in parent component want to pass property of parent component to child component (please look at index.html).

for example: if you want type property in Item component, but you cant pass it in slots.

here is the way:

var cType = this.parentNode.getAttribute('type');

How did I use the above statement in my components. also you can check dynamic styling used in child-component.

// index.html - where user use the components.

<body>
  <main>
   <ajs-container type="uniform">
    <ajs-item size="2"></ajs-item>
    <ajs-item size="3"></ajs-item>
    <ajs-item size="2"></ajs-item>
   </ajs-container>
  </main>
</body>

// parent-component

render() {
   return html`
     <div class="container">
         <slot></slot>
     </div>`;
}
customElements.define('ajs-container', Container);


// child-component

render() {
   const ItemData = html`<slot></slot>`;
   return html`
     <style>
        :host {
          ${this.hostStyle.join(';')}
        }
     </style>
     <div class="item">
         ${ItemData}
     </div>`;
}

get hostStyle() {
  const st = [];
  var cType = this.parentNode.getAttribute('type'); // by using this you can extract parent property.
  if(cType == "uniform") {
    st.push(`color: green`);
  }else {
    st.push(`color: red`);
  }
  return st;
}

customElements.define('ajs-item', Item);
0
On

If you want pass any property, value or similar you must to use a Polymer property if the way is from parent to child (with a dispatch event if it is from child to parent).

The use of a <slot> is when you have created a space where other dev wants add more content. Polymer's guide says:

To allow children to render, you can add a element to your shadow tree. Think of the <slot> as a placeholder showing where child nodes will render.

So, if you want to pass a value from parent to child I would use a property.

0
On

You pass data as property and not the child element itself. This data will be something the child element needs to render perfectly.

// Parent
 render(){
   return html`${this.list.map(data => html`<child-element .data${data}></child-element>`)}`
}

You use slot when you dont know how the child element is being rendered. Say you're creating an element that other developers will use, you dont need to know how their elements is being structure or what data is needed. All you do is to create a slot as a placeholder so any developer can insert their template.

//custom-element
render(){
   return html`<div> <slot></slot></div>`
}

// user 
render(){
return html`<custom-element>
          <my-element></my-element>
          <p>I am a paragraph in a slot</p>
          <div>You can see me too</div>
     </custom-element>`