title: JS > bind HTML onclick event to a Custom Element v1 object
body: <p><em>TL;DR</em></p>
  
  <p>How can I bind the callback of an inline onclick-event of a div element to the Custom Element, in which the div is placed?
  I want to use <code>onclick="foo('bar')"</code> instead of <code>onclick="this.foo('bar')"</code>.</p>
  
  <p><em>Long version</em>:</p>
  
  <p>Having appended an <strong>Custom Element</strong> with a <strong>clickable div</strong> to DOM as follows:</p>
  
  <pre><code>&lt;my-element&gt;
      &lt;!-- 1. works  --&gt;
      &lt;div onclick="this.foo('bar')"&gt;click me&lt;/div&gt;
  
      &lt;!-- 2. not working --&gt;
      &lt;div onclick="foo('bar')"&gt;click me&lt;/div&gt;
  
      &lt;!-- edit: 3. playground (works) --&gt;
      &lt;div onclick="me.foo('bar')"&gt;click me&lt;/div&gt;
  &lt;/my-element&gt;
  </code></pre>
  
  <p>... now I want to bind the <code>foo()</code>-function to my Custom Element (<code>&lt;my-element&gt;</code>).</p>
  
  <p><strong>1st solution</strong>: Here <code>onclick</code> calls a <code>foo()</code>-function on <code>this</code> (<code>this.foo()</code>), where <code>this</code> later gets bound to my Custom Element (see following code).</p>
  
  <p><strong>2nd solution</strong>: Here I want to omit <code>this.</code> and again bind it to my Custom Element. But: while the binding works in the above solution (1.), it does not without a prepended <code>this.</code> - that's my problem.</p>
  
  <p><strong>edited 3rd solution</strong>: Uses a Proxy to project the function call from <code>me</code> to <code>this</code> Custom Element. It doesn't solve the problem, but at least I tried.</p>
  
  <p>So the problem is: How to get solution 2 working?</p>
  
  <p>My Custom Element v1 class - including some code I tried:</p>
  
  <pre><code>class MyElement extends HTMLElement
  {
      constructor()
      {
          super()
      }
  
      connectedCallback()
      {
          var self = this
  
          this.addEventListener('click', this.handleClick, true)
  
          // Proxy for solution 3
          window.me = new Proxy({}, 
          {
              get: function(target, prop) 
              {
                  return self[prop]
              }
          })
      }
  
      handleClick(ev)
      {
          console.log(ev.target.onclick)
              // returns: ƒ onclick(event) { foo("bar") }
              // &gt; is typeof function
  
          // provides the binding to "this" for solution 1
          ev.target.onclick = ev.target.onclick.bind(this)
  
          // call
          ev.target.onclick()
              // works on first solution
              // throws error in 2nd solution: foo is not defined
      }
  
      foo(str)
      {
          console.log(str)
      }
  }
  
  customElements.define('my-element, MyElement)
  </code></pre>
  
  <p>Some explanations:</p>
  
  <ul>
  <li><p>Using <code>addEventListener</code> and setting its 3rd parameter (<code>useCapture</code>) to true, I capture the event before getting executed.</p></li>
  <li><p>I'm able to log the <code>foo()</code>-function to the console. It is encapsulated in a callable function, which seems to be the reason, why I can't bind my context to the <code>foo()</code>-function itself.</p></li>
  <li><p>Calling the function via <code>ev.target.onclick()</code> throws an error, as in the given context (<code>window</code>) no <code>foo()</code>-function exists.</p></li>
  </ul>
  
  <p>Some thoughts:</p>
  
  <ul>
  <li><p><strong>React</strong> does something similar (I haven't used React yet), but I can't see  how to transfer their solution, as they eventually somehow preprocess their onclick events (with eval?). That might be a reason why their syntax is <code>onclick={foo}</code> instead of <code>onclick="foo()"</code>. I also don't know, if passing parameters is possible in React.
  See: <a href="https://facebook.github.io/react/docs/handling-events.html" rel="nofollow noreferrer">https://facebook.github.io/react/docs/handling-events.html</a></p></li>
  <li><p>Referring to that, it might be a problem, that in my solution the <code>foo()</code> function is probably already somehow called inside the window context, what means, that it's context is already set and can't be changed anymore...? Anyways, trying to set <code>onclick="foo"</code> without brackets and calling it later  doesn't work either.</p></li>
  </ul>
  
  <p>Good read to this topic:</p>
  
  <p><a href="http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/" rel="nofollow noreferrer">http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/</a></p>
  
  <p>So, I don't know if there is a solution at all. Ideas or explanations are welcome anyways!</p>
  
  <p>EDIT 2: Fixed.</p>
  
  <p>It also works, when the element is created and appended from inside the element class:</p>
  
  <pre><code>var el = document.createElement('div')
  el.innerHTML = 'click me'
  el.onclick = () =&gt; {
      this.foo('bar')
  }
  this.appendChild(el)
  </code></pre>
  
  <p>EDIT 3, 4, 5:
  Played around a little (see solution 3) and assigned a Proxy object to a global variable ('me'), which projects any function calls to <code>this</code> Custom Element - kinda <code>__noSuchMethod__</code>. So... by choosing a 1- or 2-character-variable one could save at least a few hits on his keyboard by not typing <code>this.</code> but <code>me.</code>, <code>vm.</code> or even <code>i.</code> ... best solution so far. Sad!
  Unfortunately, solution 3 can also not be used as general pattern for all elements, as it bounds the context only to one (i.e. the last connected) Custom Element.</p>
  
  <hr>
  
  <p>EDIT 6 - Preliminary conclusions </p>
  
  <p>As it turns out, it seems not possible to bind a html-inline onclick-event (<code>onclick="foo('bar')"</code>) to the Custom Element class, in which the clickable element is embedded.</p>
  
  <p>So the most obvious ways to go to me would be:</p>
  
  <p>A) use the this keyword (like <code>onclick="this.foo('bar')"</code>) and bind it to the class as shown above. Why <code>this.foo()</code> is bindable whereas <code>foo()</code> without <code>this</code> is not, remains unclear at the moment. I wonder bc both functions do not really differ - both have already bindings: <code>this.foo(</code>) is bound to the clickable element, <code>foo()</code> is bound to <code>window</code>.</p>
  
  <p>B) use eval as suggested by @Supersharp, i.e. add an event listener to the Custom Element, listen for clicks, get the value of the onclick-attribute as string, prepend "this." to  the string and effectively do this: <code>eval("this." + "foo()")</code>.</p>
  
  <p>C) alternatively to inline onclick, I would tend to use event delegation and use declarative html attributes to indicate behaviour. To do this, again add a click event listener to the Custom Element class:</p>
  
  <pre><code>myElement.addEventListener('click', function(ev) {
  
          if (ev.target.dataset.action)
          {
              this[ev.target.dataset.action]()
          }
  
      }, false)
  </code></pre>
  
  <p>Your clickable element would look like <code>&lt;div data-action="next"&gt;Show more&lt;/div&gt;</code>.</p>