<p dir="auto">Consider wanting to create a <code class="notranslate">&lt;paper-button&gt;</code> component that can use attributes <em>or</em> properties:</p>
<p dir="auto">Attribute-based configuration:</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="  &lt;!-- Will always be disabled --&gt;
  &lt;paper-button disabled&gt;Save&lt;/button&gt;"><pre class="notranslate">  <span class="pl-c">&lt;!-- Will always be disabled --&gt;</span>
  <span class="pl-kos">&lt;</span><span class="pl-ent">paper-button</span> <span class="pl-c1">disabled</span><span class="pl-kos">&gt;</span>Save<span class="pl-kos">&lt;/</span><span class="pl-ent">button</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto">Property-based configuration:</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="  &lt;!-- Will be conditionally disabled --&gt;
  &lt;paper-button [disabled]=&quot;isDisabled&quot;&gt;Save&lt;/paper-button&gt;"><pre class="notranslate">  <span class="pl-c">&lt;!-- Will be conditionally disabled --&gt;</span>
  <span class="pl-kos">&lt;</span><span class="pl-ent">paper-button</span> <span class="pl-c1">[disabled]</span>="<span class="pl-s">isDisabled</span>"<span class="pl-kos">&gt;</span>Save<span class="pl-kos">&lt;/</span><span class="pl-ent">paper-button</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto">Good news is this works today. Bad news is that it requires a little non-intuitive massaging, and could be a lot cleaner for Angular component authors.</p>
<p dir="auto">For example, here's today's utility functions:</p>
<div class="highlight highlight-source-dart notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Utility functions shared among component authors.
dynamic getDynamic(inputValue, {defaultValue, onString(String strValue)}) {
  if (inputValue == null) {
    return defaultValue;
  } else if (inputValue is String) {
    return onString(inputValue);
  } else {
    return inputValue;
  }
}

bool getBool(
    inputValue, {
    bool defaultValue: false,
    bool onString(String strValue)}) {
  if (inputValue is String &amp;&amp; onString == null) {
    return _parseBool(inputValue, defaultValue);
  }
  return getDynamic(
      inputValue,
      defaultValue: defaultValue,
      onString: onString);
}"><pre class="notranslate"><span class="pl-c">// Utility functions shared among component authors.</span>
<span class="pl-c1">dynamic</span> <span class="pl-en">getDynamic</span>(inputValue, {defaultValue, <span class="pl-en">onString</span>(<span class="pl-c1">String</span> strValue)}) {
  <span class="pl-k">if</span> (inputValue <span class="pl-k">==</span> <span class="pl-c1">null</span>) {
    <span class="pl-k">return</span> defaultValue;
  } <span class="pl-k">else</span> <span class="pl-k">if</span> (inputValue <span class="pl-k">is</span> <span class="pl-c1">String</span>) {
    <span class="pl-k">return</span> <span class="pl-en">onString</span>(inputValue);
  } <span class="pl-k">else</span> {
    <span class="pl-k">return</span> inputValue;
  }
}

<span class="pl-c1">bool</span> <span class="pl-en">getBool</span>(
    inputValue, {
    <span class="pl-c1">bool</span> defaultValue<span class="pl-k">:</span> <span class="pl-c1">false</span>,
    <span class="pl-c1">bool</span> <span class="pl-en">onString</span>(<span class="pl-c1">String</span> strValue)}) {
  <span class="pl-k">if</span> (inputValue <span class="pl-k">is</span> <span class="pl-c1">String</span> <span class="pl-k">&amp;&amp;</span> onString <span class="pl-k">==</span> <span class="pl-c1">null</span>) {
    <span class="pl-k">return</span> <span class="pl-en">_parseBool</span>(inputValue, defaultValue);
  }
  <span class="pl-k">return</span> <span class="pl-en">getDynamic</span>(
      inputValue,
      defaultValue<span class="pl-k">:</span> defaultValue,
      onString<span class="pl-k">:</span> onString);
}</pre></div>
<p dir="auto">And the property setter itself:</p>
<div class="highlight highlight-source-dart notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// The component itself
bool _disabled = false;
void set disabled(value) {
  _disabled = getBool(value);
}"><pre class="notranslate"><span class="pl-c">// The component itself</span>
<span class="pl-c1">bool</span> _disabled <span class="pl-k">=</span> <span class="pl-c1">false</span>;
<span class="pl-k">void</span> <span class="pl-k">set</span> <span class="pl-en">disabled</span>(value) {
  _disabled <span class="pl-k">=</span> <span class="pl-en">getBool</span>(value);
}</pre></div>
<h2 dir="auto">Proposal</h2>
<p dir="auto">Have an alternative/Angular framework assisted way of doing this. Maybe annotation-based:</p>
<div class="highlight highlight-source-dart notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Attribute.onNull(false)
void set disabled(bool disabled) {
  _disabled = disabled;
}"><pre class="notranslate"><span class="pl-k">@Attribute</span>.<span class="pl-en">onNull</span>(<span class="pl-c1">false</span>)
<span class="pl-k">void</span> <span class="pl-k">set</span> <span class="pl-en">disabled</span>(<span class="pl-c1">bool</span> disabled) {
  _disabled <span class="pl-k">=</span> disabled;
}</pre></div>
<p dir="auto">I realize this could be done using pipes, but the following is needed:</p>
<ol dir="auto">
<li>Register a pipe that may or may not be used</li>
<li>Inject <code class="notranslate">PipeRegstry</code></li>
<li>Create a transformer from the registry</li>
<li>Use the transformer on the property setter</li>
</ol>
<p dir="auto">This could be a lot cleaner/simpler, and is more natural with native/web components.</p>
<p dir="auto">(Slightly related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="92945970" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/2869" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/2869/hovercard" href="https://github.com/angular/angular/issues/2869">#2869</a>)</p>
<p dir="auto">Say I have a component that needs to know about its disabled state in some event:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({
  selector: '[md-button][href]',
  bind: {disabled: 'disabled'}
})
class MdAnchor {
  onClick(event) {
    // Disabled anchors don't navigate anywhere.
    if (this.disabled) {
      event.preventDefault();
    }
  }
}"><pre class="notranslate">@<span class="pl-v">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">selector</span>: <span class="pl-s">'[md-button][href]'</span><span class="pl-kos">,</span>
  <span class="pl-c1">bind</span>: <span class="pl-kos">{</span><span class="pl-c1">disabled</span>: <span class="pl-s">'disabled'</span><span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-v">MdAnchor</span> <span class="pl-kos">{</span>
  <span class="pl-en">onClick</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Disabled anchors don't navigate anywhere.</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">event</span><span class="pl-kos">.</span><span class="pl-en">preventDefault</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></pre></div>
<p dir="auto">This will work fine if we have something like</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;a md-button href=&quot;http://google.com&quot; [disabled]=&quot;isDisabled()&quot;&gt;Google&lt;/a&gt;"><pre class="notranslate"><span class="pl-kos">&lt;</span><span class="pl-ent">a</span> <span class="pl-c1">md-button</span> <span class="pl-c1">href</span>="<span class="pl-s">http://google.com</span>" <span class="pl-c1">[disabled]</span>="<span class="pl-s">isDisabled()</span>"<span class="pl-kos">&gt;</span>Google<span class="pl-kos">&lt;/</span><span class="pl-ent">a</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto">However, if you instead do</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;a md-button href=&quot;http://google.com&quot; disabled&gt;Google&lt;/a&gt;"><pre class="notranslate"><span class="pl-kos">&lt;</span><span class="pl-ent">a</span> <span class="pl-c1">md-button</span> <span class="pl-c1">href</span>="<span class="pl-s">http://google.com</span>" <span class="pl-c1">disabled</span><span class="pl-kos">&gt;</span>Google<span class="pl-kos">&lt;/</span><span class="pl-ent">a</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto">This code will not work, as <code class="notranslate">this.disabled</code> will be the empty string. I would have to update the value in <code class="notranslate">onChange</code>:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="onChange() {
  this.disabled = this.disabled || this.disabled == '';
}"><pre class="notranslate"><span class="pl-en">onChange</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span> <span class="pl-c1">||</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span> <span class="pl-c1">==</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">or always use a method:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="isDisabled() {
  return this.disabled || this.disabled == '';
}"><pre class="notranslate"><span class="pl-en">isDisabled</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">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span> <span class="pl-c1">||</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">disabled</span> <span class="pl-c1">==</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">TL;DR: Change detection will set disabled to the empty string, which is falsy, but still implies disabled state.</p>