0

I have the following code in the parent component

    import { LightningElement, api ,track} from 'lwc';

export default class eventParent extends LightningElement {
    clickedRoom;
    meetingRoomsInfo=[
        {roomName: 'A001', roomCapacity:7},
        {roomName: 'A002', roomCapacity:10},
        {roomName: 'A003', roomCapacity:17},
        {roomName: 'B001', roomCapacity:27},
        {roomName: 'B002', roomCapacity:37},
        {roomName: 'B003', roomCapacity:47},
        {roomName: 'C001', roomCapacity:57},
        {roomName: 'C002', roomCapacity:67},
        {roomName: 'C003', roomCapacity:77}

    ];

    tileSelectHandler(event){
        console.log('inside parent handler');
        this.clickedRoom=event.detail.roomName;
        console.log('clicked room property'+this.clickedRoom);
    }

    constructor(){
        super();
        this.template.addEventListener('tileclick',this.tileSelectHandler);
    }

}

The template of the child component looks like this:

<template>
    <lightning-layout> 
        <lightning-layout-item size='8' padding="around-small">
            <ul>
                <template for:each={meetingRoomsInfo} for:item="room">
                    <li key={room.roomName}>
                        <c-event-child meeting-room-info={room} ></c-event-child>
                    </li>
                </template>
            </ul>
        </lightning-layout-item>

        <lightning-layout-item size='8'>
           {clickedRoom};
        </lightning-layout-item>
    </lightning-layout>
</template>

The event handler (tileSelectHandler) does get invoked and the clickedRoom property also gets the appropriately updated (I know because I've logged it on console). However, the clickedRoom property is not displaying on the template. Why is this so?

PS: It works fine when I use bind like this

this.template.addEventListener('tileclick',this.tileSelectHandler.bind(this);

Now the documentation says that using bind() is an anti-pattern and that we should not use it. So is there any other way of displaying the value on template?

5
  • Is there a reason not to add the handler in the template itself using ontileclick={tileSelectHandler} on the child component? – Phil W May 24 at 19:01
  • You require the bind to ensure that the listener is called correctly with the right contextual "this". It's an anti-pattern as this can cause "leaks" (especially if/when components get recycled by the Lightning Platform). You can work around this if you remember this bound function in a member and remove the event listener again during component disconnection, but that's a faff. I recommend statically binding the listener as per the above comment and my answer... – Phil W May 24 at 20:21
  • Well, there's no reason for not adding the handler to the template. In fact it works flawlessly if the handler is added to the template itself. It's just that I was going through the documentation and this was described as one of the ways of adding event listener but it doesn't work without bind and the documentation doesn't recommend using bind. So I thought there might be another way of doing it without bind. Also, are there any specific circumstances where one should add the listener programmatically instead of adding it in the markup? – randomperson May 25 at 5:02
  • Did the documentation show use of an arrow function (where this remains bound appropriately)? – Phil W May 25 at 6:20
  • @PhilW Yes you're right. The event handler in the documentation is indeed defined as an arrow function. I was not aware about the behavior of 'this' in arrow functions. I need to study a little bit about this. Thanks. – randomperson May 27 at 7:12
2

On the assumption it is the c-event-child component that exposes the "tileclick" event, simply update the parent component's template to include the event handler binding:

<template for:each={meetingRoomsInfo} for:item="room">
    <li key={room.roomName}>
        <c-event-child meeting-room-info={room} ontileclick={tileSelectHandler}></c-event-child>
    </li>
</template>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.