<p dir="auto"><strong>I'm submitting a ...</strong>  (check one with "x")</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[x] bug report =&gt; search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question"><pre class="notranslate"><code class="notranslate">[x] bug report =&gt; search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
</code></pre></div>
<p dir="auto"><strong>Current behavior</strong><br>
Using a custom element that adds a class to itself is incompatible when setting the class in a component template.</p>
<p dir="auto"><strong>Expected behavior</strong><br>
Classes set in a component template should be added to the classList, instead of overriding it.</p>
<p dir="auto"><strong>Minimal reproduction of the problem with instructions</strong></p>
<ul dir="auto">
<li>Create a custom element that modifies its classList in <code class="notranslate">connectedCallback()</code></li>
<li>Use the custom element with a class attribute in a component template</li>
</ul>
<p dir="auto">View the demo in Chrome (native webcomponent support)<br>
<a href="http://plnkr.co/edit/4pzXr214xEZyUZ9ftLG7?p=preview" rel="nofollow">http://plnkr.co/edit/4pzXr214xEZyUZ9ftLG7?p=preview</a></p>
<p dir="auto"><strong>What is the motivation / use case for changing the behavior?</strong><br>
Feeling the love between Angular and Polymer 2.</p>
<p dir="auto">Specifically, the <code class="notranslate">&lt;paper-button&gt;</code> element adds the <code class="notranslate">.paper-material</code> class to its classList <a href="https://github.com/PolymerElements/paper-button/blob/2.0-preview/paper-button.html#L170">when attached to the DOM</a>.</p>
<p dir="auto">Angular first <a href="https://github.com/angular/angular/blob/master/packages/core/src/view/element.ts#L147">creates and attaches the element</a> (and <code class="notranslate">&lt;paper-button&gt;</code> adds its class hooray!).</p>
<p dir="auto">Next, the function asks the renderer <a href="https://github.com/angular/angular/blob/master/packages/core/src/view/element.ts#L167">to set the attributes from the component markup</a>.</p>
<p dir="auto">In the browser, the <a href="https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/dom_renderer.ts#L151">renderer uses <code class="notranslate">setAttribute()</code></a> on the element. When calling <code class="notranslate">element.setAttribute('class', 'name');</code>, existing classes are removed.</p>
<p dir="auto"><strong>Suggested Fix</strong></p>
<p dir="auto">I think it makes the most sense for <code class="notranslate">DefaultDomRenderer2</code> to understand that setting the class attribute can have negative consequences.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export class DefaultDomRenderer2 implements Renderer2 {
 ...
 setAttribute(el: any, name: string, value: string, namespace?: string): void {
    if (namespace) {
      el.setAttributeNS(NAMESPACE_URIS[namespace], namespace + ':' + name, value);
    } else if (name === 'class') {
      value.split(' ').forEach(className =&gt; {
        el.classList.add(name, className);
      });
    } else {
      el.setAttribute(name, value);
    }
  }
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">class</span> <span class="pl-smi">DefaultDomRenderer2</span> <span class="pl-k">implements</span> <span class="pl-smi">Renderer2</span> <span class="pl-kos">{</span>
 ...
 <span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s1">el</span>: <span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-s1">name</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">value</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">namespace</span>?: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">namespace</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">el</span><span class="pl-kos">.</span><span class="pl-en">setAttributeNS</span><span class="pl-kos">(</span><span class="pl-smi">NAMESPACE_URIS</span><span class="pl-kos">[</span><span class="pl-s1">namespace</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-s1">namespace</span> <span class="pl-c1">+</span> <span class="pl-s">':'</span> <span class="pl-c1">+</span> <span class="pl-s1">name</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">name</span> <span class="pl-c1">===</span> <span class="pl-s">'class'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">value</span><span class="pl-kos">.</span><span class="pl-en">split</span><span class="pl-kos">(</span><span class="pl-s">' '</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">forEach</span><span class="pl-kos">(</span><span class="pl-s1">className</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-s1">el</span><span class="pl-kos">.</span><span class="pl-c1">classList</span><span class="pl-kos">.</span><span class="pl-en">add</span><span class="pl-kos">(</span><span class="pl-s1">name</span><span class="pl-kos">,</span> <span class="pl-s1">className</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
      <span class="pl-s1">el</span><span class="pl-kos">.</span><span class="pl-en">setAttribute</span><span class="pl-kos">(</span><span class="pl-s1">name</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<ul dir="auto">
<li>
<p dir="auto"><strong>Angular version:</strong> 2.4.10+</p>
</li>
<li>
<p dir="auto"><strong>Browser:</strong> [all]</p>
</li>
<li>
<p dir="auto"><strong>Language:</strong> [TypeScript 2.0.2]</p>
</li>
<li>
<p dir="auto"><strong>Node (for AoT issues):</strong> <code class="notranslate">node --version</code> =   v6.9.5</p>
</li>
</ul>
<p dir="auto">Getting this in my code as well but easier to show on the official hero form. Here is the plunk of the official hero form with the dev dependency changed into min.</p>
<p dir="auto"><a href="http://plnkr.co/edit/hKCBa1RDob5H9i9x7ZhT?p=preview" rel="nofollow">http://plnkr.co/edit/hKCBa1RDob5H9i9x7ZhT?p=preview</a></p>
<p dir="auto">There error you get is</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="No provider for t! (t -&gt; t)"><pre class="notranslate"><code class="notranslate">No provider for t! (t -&gt; t)
</code></pre></div>
<p dir="auto">And when you switch back to dev it goes away.</p>