0

In console this.unselectedPlayerList.length is not shown, It will shown before using splice method. So I have doubt in splice method.

export default class MakeYourTeamChild extends LightningElement {
    @api unselectedPlayerList=[];
    SelectPlayer(event)
    { 
        for(let index = 0 ; index < this.unselectedPlayerList.length; index++)
        {
            if(this.unselectedPlayerList[index].Name == event.target.title)
            {
                this.selectedPlayer = this.unselectedPlayerList[index].Name;
                this.unselectedPlayerList.splice(index,1);
                console.log('After Splice',this.unselectedPlayerList.length);
            }
        }
    }
}

2 Answers 2

0

As per my understanding, we can't update or edit the @api variable by using splice(), push(), and concat() methods. So, you have to replicate the @api variable in another temp variable and implement your logic on that temp variable. Assign back the temp variable to the @api variable. Have a look at the below code for reference:

export default class MakeYourTeamChild extends LightningElement {
    @api unselectedPlayerList=[];
    **let tempUnsltPlList = [];**
    SelectPlayer(event)
    { 
        for(let index = 0 ; index < this.tempUnsltPlList.length; index++)
        {
            if(this.tempUnsltPlList[index].Name == event.target.title)
            {
                this.selectedPlayer = this.tempUnsltPlList[index].Name;
                this.tempUnsltPlList.splice(index,1);
                console.log('After Splice',this.tempUnsltPlList.length);
            }
        }
       **this.unselectedPlayerList = [...tempUnsltPlList];**
    }
}

I hope it will help you. If yes, mark it as the best answer. Feel free to reach out to me!

Sign up to request clarification or add additional context in comments.

1 Comment

This answer is both correct and incorrect. Correct, because without the \@api, it would be best answer with small addition of another solution is only to add \@track as arrays are not reactive when using internal method (only = operator makes view to rerender). Incorrect, because \@api values should not be edited inside a component otherwise parent component might not correctly get the new value and it will start being confusing how the value is updated in the parent component. You should stick to the "props down, event up" logic used in all major JS framework. I gonna write my own answer.
0

You have a parent / child communication issue as I understand. As always, the best know approach is "props down, event up". This will ensure you easily understand how & when a variable change within a component and component behavior will not be changed by it's inner child component.

In your case, unselectedPlayerList is a prop on the child component filled by its parent component. This means parent component is owner of the data and controlling this prop value. If child component wants to modify the value of this value, it needs to ask the parent to do so, this is done by emitting an event telling the parent component what to do.

export default class ParentComponent extends LightningElement {
  unselectedPlayerList = []

  handleSelectPlayer (event) {
    const playerName = event.detail.playerName
    const playerIndex = this.unselectedPlayerList.findIndex(player => player.Name === playerName)

    const shallowPlayerList = [ ...this.unselectedPlayerList ]

    shallowPlayerList.splice(playerIndex, 1)

    this.unselectedPlayerList = shallowPlayerList
  }
}
<template>
  <c-child-component
    unselected-player-list={unselectedPlayerList}
    onselectplayer={handlePlayerSelect}
  ></c-child-component>
</template>

export default class ChildComponent extends LightningElement {
  @api unselectedPlayerList = []

  handleSelectPlayer (event) {
    this.dispatchEvent(
      new CustomEvent('selectplayer', {
        detail: {
          playerName: event.target.title,
        }
      })
    )
  }
}

There also is another way to write the parent component if you'd like using the @track decorator. In LWC all component attributes are reactive with a small exception around objects (array, js object). Changing an inner property of an object will not rerender the view unless decorating that object.

You can use this js for the parent component for the exact same result.

export default class ParentComponent extends LightningElement {
  @track unselectedPlayerList = []

  handleSelectPlayer (event) {
    const playerName = event.detail.playerName
    const playerIndex = this.unselectedPlayerList.findIndex(player => player.Name === playerName)

    this.unselectedPlayerList.splice(playerIndex, 1)
  }
}

I would not recommend using the @track version as it's heavier for performance and in any case you do stuff in a loop, every modification to the array will/might trigger view update. In first version you are assured that view will update only once which is also giving you more control on how the view (or dependent properties like getters) behave.

I hope this will help you and I invite you to read these articles:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.