2

I am facing a problem in the following code in my lwc component.

Whenever I try to append a child dynamically from Js in LWC component. I got this error.

HTML :

<template>
    <lightning-combobox
        name="comboType" value={comboboxValues}
        label="label" onchange={handleChange}
        placeholder="nnnn" class="margin-bottom-8"
        options={Options}
        required>
    </lightning-combobox>

    <div data-id="overview" lwc:dom="manual"></div>
</template>

JS :

    handleChange(event){

        var element = this.template.querySelector('[data-id="overview"]');

        child = '<c-lwc_simulation></c-lwc_simulation>';

        element.appendChild(child);

    }

enter image description here

1
  • Hi. You forgot to specify the error.
    – Phil W
    Mar 5, 2020 at 8:43

2 Answers 2

3

It is not possible to dynamically create LWC components from JavaScript. They can only be created within templates. You need to change your code to either leverage an iteration over some data held in the parent, like:

<template for:each={simulation} for:item="sim">
    <c-lwc_simulation key={sim.key}></c-lwc_simulation>
</template>

... or to consider using Aura (which does support dynamic component creation), or to consider some other approach (like having multiple different templates to select from).

1

It could very well be that you don't need dynamic component creation. While this is dynamic DOM creation is widely used, and probably the default behavior of a lot of web developers when creating UI features in JS, the design of LWC and the idiomatic approach to creating LWC is to create conditionally rendered elements.

There is another post in this site where Deigo Val (one of the architects of LWC) explains the approach that was taken with the framework and why. But I think it can be summed up by this one question that he asks in his answer:

Why would you want to...dynamically create a very simple leaf component?

Now in your case, I don't know what <c-lwc-simulation> is meant to be, or if it will be a "simple leaf component" as he surmises, but the architecture of creating static templates with conditional rendering is what we have to work with today. (Note, Diego does say that there may be some limited conditional rendering in the future, but no word on when just yet, last I heard.)

Reading between the lines a bit, it looks like you're going for the logic "if something is selected from the <lightning-combobox> then render something else". Going on that assumption, you need to wrap your <c-lwc-simulation> in a conditionally rendered template tag and have some data in the child LWC change the rendering based on that. I'm not certain what final outcome you're going for, but one way this could be done is as follows:

// controller code
// add a property to make rendering conditional
showLWCSimulation = false; 

...

// modify the handleChange function to flip the boolean property
handleChange(event){

    this.comboboxValues = event.target.value; 

    ...
    // perform some other logic here with the data, perhaps
    ...

    //new code
    if (this.comboboxValues === 'My Selected Value') {
        this.showLWCSimulation = true;
    }
}

If you need <c-lwc-simulation> to respond to the selected value, then create an @api enabled property to pass in some data so that you can make it respond:

import { LightningElement, api > from 'lwc'; 

export default class LwcSimulation extends LightningElement {

    @api passedInValue; 

    // other properties and functions here

}

Then in the template, something like this:

<template>
    ...
    <!-- static conditional placement of c-lwc-simulation -->
    <template if:true={showLWCSimulation}>
        <c-lwc-simulation passed-in-value={comboboxValues}></c-lwc-simulation>
    </template>
</>

Incidentally, there are uses for lwc:dom="manual", and that does work with third party libs. Why it doesn't work here, I suspect it's because you're attempting to add a custom element (which is locked down, outside the framework), versus a standard element (which is what you'd find in a third party lib).

Long story short, I think you may benefit from taking some time and understand the standard use patterns of LWC. If you'd like a bunch of examples, check out the LWC Recipes app on github.

4
  • In my parent LWC component I have to show only one child based on the value the selected value in the lightning-combobox. I've been using the same approach of what you gave as an example. but since I have more than 50 child it's pretty heavy to have to deal with more than 50 variable just to be able to know which child to make appear. that's why I was looking for a way to do in dynamic way. Mar 5, 2020 at 10:26
  • I agree...with that kind of variability, even allowing dynamic templates could be a lot of different artifacts to manage in the project. Without knowing more details, the only suggestion I can offer is to think about what part of the 50 different use cases can reused. Try to encapsulate as much of that as you can in the root child component.
    – pchittum
    Mar 5, 2020 at 10:45
  • Thank you for the explanation. Mar 5, 2020 at 11:26
  • Sure thing. And if you have a better solution, don't hesitate to come back and provide your own answer. :-)
    – pchittum
    Mar 5, 2020 at 11:27

You must log in to answer this question.

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