简体   繁体   中英

Grab an element that doesn't exist yet in the document

I'm attempting to put together a trivia card application, using the map() method to create the content/layout for each card. I have been unsuccessful at being able to 'grab' the elements (specifically the div 'answerArea') for the purpose of adding style, event listeners, etc. In attempting to assign a variable to an element and add a classList to it, I receive the error that the element is 'not defined'. Any help is appreciated.示例琐事卡片

 <style>
    h2 {
        text-align: center;
        margin: 20px 0px;
    }
    .container-template {
        width: 385px;
        height: 285px;
        margin: 2vh auto;
        background-color: lightgrey;
        display: grid;
        justify-content: center;
    }
    .card {
        display: grid;
        grid-template-columns: 1fr;
        margin: auto;
        width: 335px;
        height: 235px;
        background-color: white;
    }
    .inputs {
        margin-left: 15px;
    }
    #question {
        display: block;
        height: 35px;
        width: 225px;
    }
    #answer {
        height: 35px;
        width: 225px;
        display: block;
    }
    #subBtn {
        margin-top: 15px;
        cursor: pointer;
        margin-left: 5px;
    }
    .cardArea {
        background-color: lightgray;
        padding-bottom: 25px;
        border: 1px solid black;
        padding-left: 25px;
        width: 360px;
        margin: 2vh auto;
    }
    .answerArea {
        width: 360px;
        padding-left: 7px;
        padding-top: 5px;
        margin: auto;
        color: blue;
        /*display: none;*/
    }
    .answerText {
        display: none;
    }
    .cardQ {
        color: blue;
        margin: 5px 0px 20px 5px;
    }
    .showHide {
        text-decoration: none;
        display: block;
        margin-bottom: 15px;
    }
    .showHide:hover {
        color: orange;
    }
    .delete {
        margin-left: 20px;
    }
    .buttons {
        margin-top: 35px;
    }
</style>

<h2>TRIVIA CARDS</h2>
<div class="container-template">
    <div class="card">
        <form id="trivia-form">
            <div class="inputs">
                <p>Question:</p>
                <input type="text" id="question" name="question">
                <p>Answer:</p>
                <input type="text" id="answer" name="answer">
                <button type="submit" id="subBtn">Submit</button>
            </div>
        </form>
    </div>
</div>

<div class="cardBox"></div>


const triviaForm = document.getElementById('trivia-form');
const question = document.getElementById('question');
const answer = document.getElementById('answer');
const submit = document.getElementById('subBtn');
const cardCont = document.getElementById('cardCont');
const showAnswer = document.querySelector('.showHide');
const cardBox = document.querySelector('.cardBox');

let cards = [];

triviaForm.addEventListener('submit', function(e) {
    e.preventDefault();

    const questionData = e.currentTarget.question.value;
    const answerData = e.currentTarget.answer.value;

    if(!questionData) return;
    if(!answerData) return;

    const card = {
        questionData,
        answerData,
        id: Date.now(),
    }

    cards.push(card);

    e.target.reset();

    cardBox.dispatchEvent(new CustomEvent('cardsUpdated'));
});

function displayCards() {

    const html = cards.map(card => 
    `<div class="cardArea">
       <p class="parQ">Question:</p>
       <div class="cardQ">${card.questionData}</div>
       <a href="#" class="showHide" onclick="toggleData()">Show/Hide Answer</a>
       <div class="answerArea">${card.answerData}</div>
       <div class="buttons">
          <button type="submit" onclick="edit()">Edit</button>
          <button type="submit" onclick="omit()"class="delete">Delete</button>
       </div>
    </div>`
    ).join('');
   
    cardBox.innerHTML = html;
}

function toggleData(e) { 
    
}

function mirrorToLocalStorage() {
    localStorage.setItem('cards', JSON.stringify(cards));
}

function restorefromLocalStorage() {
    const lsItems = JSON.parse(localStorage.getItem('cards'));
    if(lsItems.length) {
        cards.push(...lsItems);
        cardBox.dispatchEvent(new CustomEvent('cardsUpdated'));
    }
}

cardBox.addEventListener('cardsUpdated', displayCards);
cardBox.addEventListener('cardsUpdated', mirrorToLocalStorage);

restorefromLocalStorage();

You'll need to do whatever you need to do with it after you've created. So after you set the cardBox inner HTML, you'll need to bind the events to it. Presumably using element.addEventListener or similar.

The issue is that until it has been created, it doesn't exist so you can't reference it or do anything with it. Hence the need to do it after creating it. Alternatively, have it there from the start but with display: none; and then modify it as required and make it visible instead of adding it to the DOM.

Also just a heads up, you'll want to be careful with sanitising input if you're using .innerHTML as people can inject javascript and other code into there which can potentially cause security issues if the stuff people enter ever leaves their session.

You can bind an event listener to cardBox and do the toggling there. Something like:

function doToggleHide(params) {
// Look for `card-${params.id}` and hide/display `.answerArea`
}

cardBox.addEventListener("toggleHide", doToggleHide);

function toggleData(id) {
  var evt = new CustomEvent("toggleHide", {id: id});
  cardBox.dispatchEvent(evt);
}

function displayCards() {
    const html = cards.map(card => 
    `<div class="cardArea" id="card-${card.id}">
       <p class="parQ">Question:</p>
       <div class="cardQ">${card.questionData}</div>
       <a href="#" class="showHide" onclick="toggleData(${card.id})">Show/Hide Answer</a>
       <div class="answerArea">${card.answerData}</div>
       <div class="buttons">
          <button type="submit" onclick="edit()">Edit</button>
          <button type="submit" onclick="omit()"class="delete">Delete</button>
       </div>
    </div>`
    ).join('');
   
    cardBox.innerHTML = html;
}

Didn't test, but that's roughly the idea.

Possibly not passing on this when calling the toggleData function.

 const cards = [{ questionData: "Capital of The Netherlands", answerData: "Amsterdam" }]; const cardBox = document.getElementById("cardbox"); displayCards(); function displayCards() { const html = cards.map(card => `<div class="cardArea"> <p class="parQ">Question:</p> <div class="cardQ">${card.questionData}</div> <a href="#" class="showHide" onclick="toggleData(this)">Show/Hide Answer</a> <div class="answerArea">${card.answerData}</div> <div class="buttons"> <button type="submit" onclick="edit()">Edit</button> <button type="submit" onclick="omit()"class="delete">Delete</button> </div> </div>` ).join(''); cardBox.innerHTML = html; } function toggleData(e) { e.nextElementSibling.style.display = "block"; }
 .answerArea { display: none; }
 <div id="cardbox"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM