如何将删除方法绑定到渲染的网络组件

huangapple go评论65阅读模式
英文:

How to bind a delete method to a rendered web component

问题

我有困难弄清楚如何绑定我的handleDelete方法。

我结构化的方式是,用户点击加号按钮,然后数据对象被存储在窗口对象上的一个数组中。然后调用SelectedProducts组件上的渲染,它呈现一个卡片,其中有我试图绑定handleDelete方法的按钮。

如果运行代码,你可以看到我目前的进展。

也许这不是正确的方法,只是尝试不添加库来做。

仍在努力弄清楚我需要哪些生命周期方法或自定义事件?

class SelectedProducts extends HTMLElement {
  constructor() {
    super();
    this.mockData = [
      { id: 1, name: 'name-1', qty: 1 },
      { id: 2, name: 'name-2', qty: 1 },
      { id: 2, name: 'name-1', qty: 2 },
    ];
  }
  handleDelete(e) {
    e.preventDefault();
    console.log('called handleDelete');
  }

  connectedCallback() {
    this.querySelector('button').addEventListener('click', this.handleDelete.bind(this));
  }

  attributeChangedCallback(attrName, oldValue, newValue) {
    console.log('attributeChange called');
    this.handleDelete(e);
  }

  static get observedAttributes() {
    return ['data-id'];
  }

  disconnectedCallback() {
    console.log('disconnectedCallback ran');
  }

  render() {
    this.mockData.forEach((item, index) => {
      this.innerHTML += `
      <div style="display:flex; align-items: center; background-color:white; padding:15px; ">
        <button data-id="${item.id}" class="delete-btn">
          Delete me
        </button>
      </div>
      `;
    });
  }

  handleDelete(e) {
    e.preventDefault();
    alert('Called Handle delete');
  }
}
customElements.define('selected-products', SelectedProducts);

class ProductCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({
      mode: 'open',
    });

    this.shadowRoot.innerHTML =
      `<style>
      ::slotted(div){
        color: #4B5563; 
        font-weight: 900; 
        text-align: center; 
        font-size: 20px; 
      }
      </style>
      ` +
      ` <div style="background: white; margin-right: 15px;">
          <slot name="button"></slot>
          <slot name="img"></slot>
        </div>
      `;
  }
}

customElements.define('product-card', ProductCard);

class SelectBtn extends HTMLElement {
  constructor() {
    super();
    // This is called with render below
    this.itemsPicked = document.querySelector('selected-products');
    this.attachShadow({
      mode: 'open',
    });
    this.shadowRoot.innerHTML = `
    <button
    aria-label="Select"
    type="button"
    class="pressed"
    data-addbtn="add-btn"
  >
   +
  </button>
    
    `;

    this.id = this.getAttribute('id');
    this.name = this.getAttribute('name');
    this.shadowRoot
      .querySelectorAll('button')
      .forEach((button) => button.addEventListener('click', this.handleSelect.bind(this)));
  }
  // Get data from attributes & store object in
  // an array on window object
  handleSelect(e) {
    e.preventDefault();
    this.itemsPicked.render();
  }
}

customElements.define('select-button', SelectBtn);
<body>
    <div style="display: flex; justify-content: center; align-items: center; background: lightblue; padding: 10px">
      <product-card>
        <div slot="button">
          <select-button id="1" name="product name"></select-button>
        </div>
        <div slot="img">
          <div style="height: 100px; width: 100px">Select Button</div>
        </div>
      </product-card>
      <div>
        <selected-products></selected-products>
      </div>
    </div>
    <script src="app.js"></script>
    <script>
      window.selectedItems = {
        items: [],
      };
    </script>
  </body>
英文:

I am having trouble figuring out how to bind my handleDelete method.

The way I have it structured is the user clicks the plus button then data objects get stored in an array on the window object. Then render is called on the SelectedProducts component that renders a card that has the button I am trying to bind the handleDelete method to.

If you run the code you can see what I have so far.

Maybe this is not the right approach just trying to do it with out adding a library.

Still trying to wrap my head around which lifecycle methods I need or a custom event?

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

class SelectedProducts extends HTMLElement {
constructor() {
super();
this.mockData = [
{ id: 1, name: &#39;name-1&#39;, qty: 1 },
{ id: 2, name: &#39;name-2&#39;, qty: 1 },
{ id: 2, name: &#39;name-1&#39;, qty: 2 },
];
}
handleDelete(e) {
e.preventDefault();
console.log(&#39;called handleDelete&#39;);
}
connectedCallback() {
this.querySelector(&#39;button&#39;).addEventListener(&#39;click&#39;, this.handleDelete.bind(this));
}
attributeChangedCallback(attrName, oldValue, newValue) {
console.log(&#39;attributeChange called&#39;);
this.handleDelete(e);
}
static get observedAttributes() {
return [&#39;data-id&#39;];
}
disconnectedCallback() {
console.log(&#39;disconnectedCallback ran&#39;);
}
render() {
this.mockData.forEach((item, index) =&gt; {
this.innerHTML += `
&lt;div style=&quot;display:flex; align-items: center; background-color:white; padding:15px; &quot;&gt;
&lt;button data-id=&quot;${item.id}&quot; class=&quot;delete-btn&quot;&gt;
Delete me
&lt;/button&gt;
&lt;/div&gt;
`;
});
}
handleDelete(e) {
e.preventDefault();
alert(&#39;Called Handle delete&#39;);
}
}
customElements.define(&#39;selected-products&#39;, SelectedProducts);
class ProductCard extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: &#39;open&#39;,
});
this.shadowRoot.innerHTML =
`&lt;style&gt;
::slotted(div){
color: #4B5563; 
font-weight: 900; 
text-align: center; 
font-size: 20px; 
}
&lt;/style&gt;
` +
` &lt;div style=&quot;background: white; margin-right: 15px;&quot;&gt;
&lt;slot name=&quot;button&quot;&gt;&lt;/slot&gt;
&lt;slot name=&quot;img&quot;&gt;&lt;/slot&gt;
&lt;/div&gt;
`;
}
}
customElements.define(&#39;product-card&#39;, ProductCard);
class SelectBtn extends HTMLElement {
constructor() {
super();
// This is called with render below
this.itemsPicked = document.querySelector(&#39;selected-products&#39;);
this.attachShadow({
mode: &#39;open&#39;,
});
this.shadowRoot.innerHTML = `
&lt;button
aria-label=&quot;Select&quot;
type=&quot;button&quot;
class=&quot;pressed&quot;
data-addbtn=&quot;add-btn&quot;
&gt;
+
&lt;/button&gt;
`;
this.id = this.getAttribute(&#39;id&#39;);
this.name = this.getAttribute(&#39;name&#39;);
this.shadowRoot
.querySelectorAll(&#39;button&#39;)
.forEach((button) =&gt; button.addEventListener(&#39;click&#39;, this.handleSelect.bind(this)));
}
// Get data from attributes &amp; store object in
// an array on window object
handleSelect(e) {
e.preventDefault();
this.itemsPicked.render();
}
}
customElements.define(&#39;select-button&#39;, SelectBtn);

<!-- language: lang-html -->

&lt;body&gt;
&lt;div style=&quot;display: flex; justify-content: center; align-items: center; background: lightblue; padding: 10px&quot;&gt;
&lt;product-card&gt;
&lt;div slot=&quot;button&quot;&gt;
&lt;select-button id=&quot;1&quot; name=&quot;product name&quot;&gt;&lt;/select-button&gt;
&lt;/div&gt;
&lt;div slot=&quot;img&quot;&gt;
&lt;div style=&quot;height: 100px; width: 100px&quot;&gt;Select Button&lt;/div&gt;
&lt;/div&gt;
&lt;/product-card&gt;
&lt;div&gt;
&lt;selected-products&gt;&lt;/selected-products&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
window.selectedItems = {
items: [],
};
&lt;/script&gt;
&lt;/body&gt;

<!-- end snippet -->

答案1

得分: 0

我解决这个问题的方法不是将事件监听器附加到内部HTML本身,而是创建了另一个Web组件(delete-button),并为其添加了事件监听器和处理事件的方法。任何反馈都将非常酷。

class DeleteButton extends HTMLElement {
  constructor() {
    super();
    this.selectedProducts = document.querySelector('selected-products');
    this.querySelectorAll('button').forEach((button) => button.addEventListener('click', this.handleDelete.bind(this)));
  }

  handleDelete(e) {
    e.preventDefault();
    alert('Delete button Event');
  }
}
customElements.define('delete-button', DeleteButton);

class SelectedProducts extends HTMLElement {
  constructor() {
    super();
    this.mockData = [
      { id: 1, name: 'name-1', qty: 1 },
      { id: 2, name: 'name-2', qty: 1 },
      { id: 2, name: 'name-1', qty: 2 },
    ];
  }

  render() {
    this.mockData.forEach((item, index) => {
      this.innerHTML += `
      <div style="display:flex; align-items: center; background-color:white; padding:15px;">
        <delete-button>
          <button data-id="${item.id}" class="delete-btn">
            Delete me
          </button>
        </delete-button>
      </div>
      `;
    });
  }

  handleDelete(e) {
    e.preventDefault();
    alert('Called Handle delete');
  }
}
customElements.define('selected-products', SelectedProducts);

class ProductCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({
      mode: 'open',
    });

    this.shadowRoot.innerHTML =
      `<style>
      ::slotted(div){
        color: #4B5563; 
        font-weight: 900; 
        text-align: center; 
        font-size: 20px; 
      }
      </style>` +
      ` <div style="background: white; margin-right: 15px;">
          <slot name="button"></slot>
          <slot name="img"></slot>
        </div>
      `;
  }
}
customElements.define('product-card', ProductCard);

class SelectBtn extends HTMLElement {
  constructor() {
    super();
    this.itemsPicked = document.querySelector('selected-products');
    this.attachShadow({
      mode: 'open',
    });
    this.shadowRoot.innerHTML = `
    <button
    aria-label="Select"
    type="button"
    class="pressed"
    data-addbtn="add-btn"
  >
   +
  </button>
    
    `;

    this.id = this.getAttribute('id');
    this.name = this.getAttribute('name');
    this.shadowRoot
      .querySelectorAll('button')
      .forEach((button) => button.addEventListener('click', this.handleSelect.bind(this)));
  }
  handleSelect(e) {
    e.preventDefault();
    this.itemsPicked.render();
  }
}
customElements.define('select-button', SelectBtn);
<body>
    <div style="display: flex; justify-content: center; align-items: center; background: lightblue; padding: 10px">
      <product-card>
        <div slot="button">
          <select-button id="1" name="product name"></select-button>
        </div>
        <div slot="img">
          <div style="height: 100px; width: 100px">Select Button</div>
        </div>
      </product-card>
      <div>
        <selected-products></selected-products>
      </div>
    </div>
    <script src="app.js"></script>
    <script>
      window.selectedItems = {
        items: [],
      };
    </script>
  </body>
英文:

The way I solved this problem was not to attach an event listener to inner html itself. Instead I created another web component (delete-button) with and event listener and a method to handle the event. Any feedback would be super cool.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

class DeleteButton extends HTMLElement {
constructor() {
super();
this.selectedProducts = document.querySelector(&#39;selected-products&#39;);
this.querySelectorAll(&#39;button&#39;).forEach((button) =&gt; button.addEventListener(&#39;click&#39;, this.handleDelete.bind(this)));
}
handleDelete(e) {
e.preventDefault();
alert(&#39;Delete button Event&#39;);
}
}
customElements.define(&#39;delete-button&#39;, DeleteButton);
class SelectedProducts extends HTMLElement {
constructor() {
super();
this.mockData = [
{ id: 1, name: &#39;name-1&#39;, qty: 1 },
{ id: 2, name: &#39;name-2&#39;, qty: 1 },
{ id: 2, name: &#39;name-1&#39;, qty: 2 },
];
}
render() {
this.mockData.forEach((item, index) =&gt; {
this.innerHTML += `
&lt;div style=&quot;display:flex; align-items: center; background-color:white; padding:15px; &quot;&gt;
&lt;delete-button&gt;
&lt;button data-id=&quot;${item.id}&quot; class=&quot;delete-btn&quot;&gt;
Delete me
&lt;/button&gt;
&lt;/delete-button&gt;
&lt;/div&gt;
`;
});
}
handleDelete(e) {
e.preventDefault();
alert(&#39;Called Handle delete&#39;);
}
}
customElements.define(&#39;selected-products&#39;, SelectedProducts);
class ProductCard extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: &#39;open&#39;,
});
this.shadowRoot.innerHTML =
`&lt;style&gt;
::slotted(div){
color: #4B5563; 
font-weight: 900; 
text-align: center; 
font-size: 20px; 
}
&lt;/style&gt;
` +
` &lt;div style=&quot;background: white; margin-right: 15px;&quot;&gt;
&lt;slot name=&quot;button&quot;&gt;&lt;/slot&gt;
&lt;slot name=&quot;img&quot;&gt;&lt;/slot&gt;
&lt;/div&gt;
`;
}
}
customElements.define(&#39;product-card&#39;, ProductCard);
class SelectBtn extends HTMLElement {
constructor() {
super();
// This is called with render below
this.itemsPicked = document.querySelector(&#39;selected-products&#39;);
this.attachShadow({
mode: &#39;open&#39;,
});
this.shadowRoot.innerHTML = `
&lt;button
aria-label=&quot;Select&quot;
type=&quot;button&quot;
class=&quot;pressed&quot;
data-addbtn=&quot;add-btn&quot;
&gt;
+
&lt;/button&gt;
`;
this.id = this.getAttribute(&#39;id&#39;);
this.name = this.getAttribute(&#39;name&#39;);
this.shadowRoot
.querySelectorAll(&#39;button&#39;)
.forEach((button) =&gt; button.addEventListener(&#39;click&#39;, this.handleSelect.bind(this)));
}
// Get data from attributes &amp; store object in
// an array on window object
handleSelect(e) {
e.preventDefault();
this.itemsPicked.render();
}
}
customElements.define(&#39;select-button&#39;, SelectBtn);

<!-- language: lang-html -->

&lt;body&gt;
&lt;div style=&quot;display: flex; justify-content: center; align-items: center; background: lightblue; padding: 10px&quot;&gt;
&lt;product-card&gt;
&lt;div slot=&quot;button&quot;&gt;
&lt;select-button id=&quot;1&quot; name=&quot;product name&quot;&gt;&lt;/select-button&gt;
&lt;/div&gt;
&lt;div slot=&quot;img&quot;&gt;
&lt;div style=&quot;height: 100px; width: 100px&quot;&gt;Select Button&lt;/div&gt;
&lt;/div&gt;
&lt;/product-card&gt;
&lt;div&gt;
&lt;selected-products&gt;&lt;/selected-products&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
window.selectedItems = {
items: [],
};
&lt;/script&gt;
&lt;/body&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月19日 08:26:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定