javascript - 从模板字符串/文字中获取元素的 ID

标签 javascript html firebase

我正在尝试使用 addEventListener 获取下面的按钮。它如何返回null。 html 是使用模板字符串从 js 呈现的。所以我想要实现的是 addEventListener 来删除模板字符串中的按钮。

// This is the template string
data.forEach(doc => {
        checkin = doc.data();
        card = `
        <div class="carousel-item fieldId" data-id="${doc.id}">
        <div class="col-12">
            <div class="card checkCard" style="margin: 0 auto;">
                <img src="${checkin.photo}" class="card-img-top" alt="...">
                <button type="submit" class="btn center delete">
                    <i class="material-icons" style="font-size: 1em;">delete_forever</i>
                </button>
                <div class="card-body">
                    <h5 class="card-title">${checkin.title}</h5>
                    <p class="card-text">${checkin.description}</p>
                </div>
            </div>
        </div>
        </div> 

        `;
        html += card;
    });

    checkinList.innerHTML = html;


//This is the delete button

const deleteContent = document.querySelector('.delete');
deleteContent.addEventListener('click', (e) => {
    // get current document ID
    console.log('hmm')
    e.stopPropagation();
    let id = $('.carousel-item').attr('data-id')
    db.collection("checkin").doc(id).delete().then(() => {
        console.log(id + "successfully deleted!");
        $('.carousel-item').attr('data-id')
    }).catch(function (error) {
        console.error("Error removing document: ", error);
    });
});

这是控制台的错误

Uncaught TypeError: Cannot read property 'addEventListener' of null
    at index.js:123
(anonymous) @ index.js:123

最佳答案

希望我已经概述了我为使其正常工作所做的所有更改:

  1. 正如评论中所指出的,ID 必须是唯一的。类通常更适合用作 JavaScript(和 CSS) Hook 。许多人现在使用 js- 前缀来帮助维护代码时遵循 HTML -> JS 的逻辑,所以我建议这样做。
  2. document.querySelector('.delete') 只会得到一个元素 - 您在这里需要 querySelectorAll,因为每个项目都有一个删除按钮。
  3. $('.carousel-item') 是(我假设)一个 jQuery 函数调用。这将获取文档中的所有 .carousel-item 元素,而 .attr('data-id') 将仅获取第一个元素的属性。如果你想在这里使用 jQuery,你会想要从按钮元素上升到 DOM,如 $(e.target).parent('.carousel-item')。但是,由于其他代码未使用 jQuery,因此使用 e.target.closest('.js-carousel-item') 会更一致,imo。然后,要获取data-id,我们可以很容易地使用element.dataset.id
  4. > Don't use globals for this就像sao建议的那样
  5. 我不确定您示例中的 data 是否来自对 db.collection('checkin').get() 的调用,但如果它是如果您的删除按钮代码未嵌套在 then() 回调中,您将在您的代码中而不是快照本身遇到问题。
  6. 这更像是一个可选的旁注,但是通过将代码重构为使用 async/await,您的代码可以变得更具可读性。

我根据下面的示例包含了一个工作片段来演示:

;(() => {
  // My attempt at a quick mock of Firebase to make this work as a snippet
  const db = {
    _collections: {
      'checkin': [
        {
          id: 1,
          photo: 'https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1267&q=80',
          title: 'airplane w/ trees',
          description: 'airplane on ground surrounded with trees',
        }, {
          id: 2,
          photo: 'https://images.unsplash.com/photo-1485550409059-9afb054cada4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=701&q=80',
          title: 'head to head',
          description: 'minifigure head lot',
        },
      ],
    },
    collection(key) {
      const c = this._collections[key];
      const doc = (id) => ({
        id,
        data() {
          return c.find(o => o.id === id);
        },
        async delete() {
          const idx = c.findIndex(o => o.id === id);
          c.splice(idx, 1);
        },
      });
      return {
        doc,
        async get() {
          return c.map(o => o.id).map(doc);
        },
      };
    },
  }
  
  const render = () => {
    db.collection('checkin').get().then(snapshot => {
      const cards = snapshot.map(doc => {
        const checkin = doc.data();
        return `
          <div class="js-carousel-item carousel-item fieldId" data-id="${doc.id}">
            <div class="col-12">
              <div class="card checkCard" style="margin: 0 auto;">
                <img src="${checkin.photo}" class="card-img-top" alt="...">
                <button class="js-delete" type="submit" class="btn center">
                <i class="material-icons" style="font-size: 1em;">delete_forever</i>
                </button>
                <div class="card-body">
                  <h5 class="card-title">${checkin.title}</h5>
                  <p class="card-text">${checkin.description}</p>
                </div>
              </div>
            </div>
          </div>`;
      });
      document.querySelector('.js-checkin-list').innerHTML = cards.join('');
  
      // This is the delete button
      const deleteButtons = document.querySelectorAll('.js-delete');
      const deleteHandler = (e) => {
        e.stopPropagation();
        const el = e.target.closest('.js-carousel-item');
        const id = +el.dataset.id;
        db.collection('checkin').doc(id).delete().then(() => {
          console.log(`${id} successfully deleted!`);
        }).catch((error) => {
          console.error('Error removing document: ', error);
        })
        render();
      }
      deleteButtons.forEach(
        btn => btn.addEventListener('click', deleteHandler)
      );
    });
  };
  render();
})();
<div class="js-checkin-list carousel"></div>

关于javascript - 从模板字符串/文字中获取元素的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57976075/

相关文章:

javascript - 在 javascript 中从 Blob/文件创建 SHA-256 哈希

javascript - 我如何渲染这张 map ?

html - Bootstrap - 在 .fluid-container 内带有盒装网格的 Div

javascript - 为什么 JQuery 不显示 div

javascript - 构建 Electron 应用程序后,Firebase无法进行身份验证

swift - 限制非高级用户每天只能写入一次 firebase 数据库

javascript - Livefyre 和 Wordpress - 显示帖子的评论总数

javascript - 从 jQuery 设置 cookie 并从 php 读取的正确方法

php - 如何使用 CSS 对表格进行格式化

ios - 访问所有firebase用户的信息