Search code examples
javascripthtmldebuggingdombootstrap-5

Why don't HTML elements added to the DOM using JS have Bootstrap properties?


I am working on a project which uses bootstrap to create various nested components which are styled according to Bootstrap's class system. I have already created what I deem a successful card component using bootstrap, but when trying to clone this element using the exact same classes and layout using JS and the DOM system, the appended card component has HTML default styles rather than bootstrap's styles. The classes and nesting are exactly the same.

I tried combing through my code line by line and making sure that the layout was an exact duplicate. Here is an example of my base HTML code not produced by JS:

<div class="row bookContainer">
            <div class="col-md-4">
                <div class="card">
                    <div class="card-body">
                        <div class="card-title">Title Here</div>
                        <div class="card-text">
                            <p>By Mr. Ipsum Dolor</p>
                            <p>Pages: 2000</p>
                            <button type="button" class="btn btn-outline-success  complete">Completed</button>
                            <button type="button" class="btn btn-outline-danger">Remove</button>

                        </div>
                    </div>
                </div>

            </div>

        </div>

and an accompanying image of the card it produced:

Successful component.

I then used the following JS code to produce the a clone of the element layout and add it to the DOM:

Step 1: Converting book object to html

function bookToCard(book) {
    //col div
    const colDiv = createDiv();
    colDiv.classList.add("col-md-4");

    //card div
    const card = createDiv()
    card.classList.add("card");

    //card body
    const cardBody = createDiv();
    cardBody.classList.add("card-body");

    //card title
    const cardTitle = createDiv();
    cardTitle.classList.add("card-title");


    //adding title content
    let titleContent = createText(book.title);
    cardTitle.appendChild(titleContent);
    cardBody.appendChild(cardTitle);


    //card text and content
    const cardText = createDiv();
    cardText.classList.add("card-text");

    let authorParagraph = document.createElement("p");
    authorParagraph.appendChild(createText(book.author));

    cardText.appendChild(authorParagraph);

    let numParagraph = document.createElement("p");
    numParagraph.appendChild(createText(book.pages));

    cardText.appendChild(numParagraph);

    //buttons
    let cButton = document.createElement("button"); //complete or incomplete button
    cButton.classList.add("btn");
    if (book.completed) {
        cButton.classList.add("btn-outline-success");
    } else {
        cButton.classList.add("btn-outline-secondary");
    }
    cardText.appendChild(cButton);

    let rButton = document.createElement("button");
    rButton.classList.add("btn", "btn-outline-danger");
    cardText.appendChild(rButton);

    cardBody.appendChild(cardText);

    card.appendChild(cardBody);

    colDiv.appendChild(card);

    return colDiv;
}

Step 2: updating HTML display

function updateDisplay() {
    let container = document.querySelector(".bookContainer");
    container.innerHTML = '';
    container.classList.add("row", "bookContainer");
    for (let i = 0; i < library.length; i++) {
        container.appendChild(bookToCard(library[i]));
    }

}

The process results in the following element being added to the page (with the successful version shown at left):

enter image description here.

Any help on how to get the right card to have Bootstrap properties would be appreciated. Sorry for the sloppy code.


Solution

  • Based on the images, the issue is not the styling, as bootstrap classes have been applied to the new card. The issue is you forgetting to add text to created <button>s and <div>s.

    For cButton

    let cButton = document.createElement("button"); 
    cButton.classList.add("btn");
    if (book.completed) {
        cButton.classList.add("btn-outline-success");
        cButton.textContent = "Completed"; // <<<<<<<<<<<<<< here
    } else {
        cButton.classList.add("btn-outline-secondary");
        cButton.textContent = "In Progress"; // <<<<<<<<<<<<<< and here
    }
    

    And for author

    let authorParagraph = document.createElement("p");
    authorParagraph.appendChild("By " + createText(book.author));  // <<<<< added "By "
    

    Need to do the same for pages and Remove