0

html file of child component

<template>
    <p>I am Child component</p>
    <div class="vertical-menu">
        <template for:each={navList} for:item="list">
            <a href="javascript:void(0);" class={list.className} name={{list.name}} key={list.id}
                onclick={handleNavSelection}>{list.name}</a>
        </template>
    </div>
</template>

JS File of child component

import { LightningElement, api } from 'lwc';

export default class NavbarChildComponent extends LightningElement {
    @api navList;
    handleNavSelection(event) {
        event.preventDefault();
        const selectEvent = new CustomEvent('selection', {
            detail: event.target.name
        });
        // Fire the custom event
        this.dispatchEvent(selectEvent);
    }
}

JS file of parent component

import { LightningElement } from 'lwc';

export default class NavbarParentComponent extends LightningElement {
    selectedPlayer = null;
    navList = [
        {
            id: 1,
            name: 'Virat Kohli',
            imgUrl:
                'https://www.cricbuzz.com/a/img/v1/152x152/i1/c170661/virat-kohli.jpg',
            country: 'India',
            rating: '922',
            position: '1',
            selected: false
        },
        {
            id: 2,
            name: 'Steven Smith',
            imgUrl:
                'https://www.cricbuzz.com/a/img/v1/152x152/i1/c170624/steven-smith.jpg',
            country: 'Australia',
            rating: '913',
            position: '2',
            selected: false
        },
        {
            id: 3,
            name: 'Kane Williamson',
            imgUrl:
                'https://www.cricbuzz.com/a/img/v1/152x152/i1/c170733/kane-williamson.jpg',
            country: 'New Zealand',
            rating: '887',
            position: '3',
            selected: false
        },
        {
            id: 4,
            name: 'Joe Root',
            imgUrl:
                'https://www.cricbuzz.com/a/img/v1/152x152/i1/c170942/joe-root.jpg',
            country: 'England',
            rating: '710',
            position: '4',
            selected: false
        },
        {
            id: 5,
            name: 'David Warner',
            imgUrl:
                'https://www.cricbuzz.com/a/img/v1/152x152/i1/c170635/david-warner.jpg',
            country: 'Australia',
            rating: '687',
            position: '5',
            selected: false
        }
    ];
    selectedNavHandler(event) {
        const playerName = event.detail;
        this.selectedPlayer = this.navList.find(
            item => item.name === playerName
        );
    }
}

HTML file of Parent Component

<template>
    <lightning-card title="Event with Data" icon-name="custom:custom14">
        <div class="slds-m-around_medium">
    <h3>
        select your favourite cricketer in child component and see details in
        parent component
    </h3>
    <div class="flex">
        <p>I am parent component</p>
        <c-navbar-child-component nav-list={navList} onselection={selectedNavHandler}></c-navbar-child-component>

        <template if:true={selectedPlayer}>
            <div class="card">
                <div>
                    <img src={selectedPlayer.imgUrl} alt="Avatar" style="width:100%" />
                </div>
                <div class="container">
                    <p><strong>Player Name:</strong> {selectedPlayer.name}</p>
                    <p><strong>Ranking:</strong> {selectedPlayer.position}</p>
                    <p><strong>country:</strong> {selectedPlayer.country}</p>
                    <p><strong>Rating:</strong> {selectedPlayer.rating}</p>
                </div>
            </div>
        </template>
    </div>
</div>
</lightning-card>
</template>

In the child component, html file I didn't understand why for the name attribute, there are double closing braces included and why class={list.className} is required. What is its purpose?

2 Answers 2

1

class={list.className}

Basically class is used for applying CSS. If you want to apply CSS dynamically then you have to give dynamic class acc. to it. Link

1
  • okaay...and what about that name={{list.name}}? why double braces over there?
    – Oswald
    Commented Nov 20, 2022 at 19:14
0

I think the name={{item.name}} is just plain wrong - on two counts. The idea of the code is to send an event up from the child to the parent and you will see event.target.name is being used to send the name of the selected record in the js of the child.

It is better to use the data attributes (see https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) so best practice is to say do data-id={name.id} and then use event.target.dataset.id which will then post the id of the record to the parent. It is also incorrect to use the name as a unique identifier as their may be crickets of the same name (although obviously only one Kirat Kohli !!).

So in summary

  1. {{ is incorrect and should be {
  2. use data attributes and change to data-id and then pass this up

A similar example but around a table of results see http://andynix.uk/opening-records-from-a-table

These are the changes you need to make to the code:

<template>
  <p>I am Child component</p>
  <div class="vertical-menu">
    <template for:each={navList} for:item="list">
      <a
        href="javascript:void(0);"
        class={list.className}
        data-id={list.id}
        key={list.id}
        onclick={handleNavSelection}
        >{list.name}</a
      >
    </template>
  </div>
</template>

and

 handleNavSelection(event) {
    event.preventDefault();
    const selectEvent = new CustomEvent("selection", {
      detail: event.target.dataset.id
    });
    // Fire the custom event
    this.dispatchEvent(selectEvent);
  }

and

import { LightningElement } from "lwc";

export default class NavbarParentComponent extends LightningElement {
  selectedPlayer = null;
  navList = [
    {
      id: "1",
      name: "Virat Kohli",
      imgUrl:
        "https://www.cricbuzz.com/a/img/v1/152x152/i1/c170661/virat-kohli.jpg",
      country: "India",
      rating: "922",
      position: "1",
      selected: false
    },
    {
      id: "2",
      name: "Steven Smith",
      imgUrl:
        "https://www.cricbuzz.com/a/img/v1/152x152/i1/c170624/steven-smith.jpg",
      country: "Australia",
      rating: "913",
      position: "2",
      selected: false
    },
    {
      id: "3",
      name: "Kane Williamson",
      imgUrl:
        "https://www.cricbuzz.com/a/img/v1/152x152/i1/c170733/kane-williamson.jpg",
      country: "New Zealand",
      rating: "887",
      position: "3",
      selected: false
    },
    {
      id: "4",
      name: "Joe Root",
      imgUrl:
        "https://www.cricbuzz.com/a/img/v1/152x152/i1/c170942/joe-root.jpg",
      country: "England",
      rating: "710",
      position: "4",
      selected: false
    },
    {
      id: "5",
      name: "David Warner",
      imgUrl:
        "https://www.cricbuzz.com/a/img/v1/152x152/i1/c170635/david-warner.jpg",
      country: "Australia",
      rating: "687",
      position: "5",
      selected: false
    }
  ];
  selectedNavHandler(event) {

    const playerId = event.detail;
    this.selectedPlayer = this.navList.find((item) => item.id === playerId);
  }
}

Note that the original object of cricketers has the id as a string so id : "1" as you are getting a string back on the event.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .