<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davis</title>
    <description>The latest articles on DEV Community by Davis (@davismj).</description>
    <link>https://dev.to/davismj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F119494%2F90dfce50-4b40-4a15-9137-fc85897fbbff.png</url>
      <title>DEV Community: Davis</title>
      <link>https://dev.to/davismj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davismj"/>
    <language>en</language>
    <item>
      <title>Perfect Select All Checkbox in 3 Lines of Aurelia Code</title>
      <dc:creator>Davis</dc:creator>
      <pubDate>Sat, 09 Nov 2019 19:17:58 +0000</pubDate>
      <link>https://dev.to/davismj/perfect-select-all-checkbox-in-3-lines-of-aurelia-code-am7</link>
      <guid>https://dev.to/davismj/perfect-select-all-checkbox-in-3-lines-of-aurelia-code-am7</guid>
      <description>&lt;p&gt;Standard HTML checkboxes have some superpowers in Aurelia, but I'm always astonished to find out when one of my customers isn't taking full advantage of them. In addition to the standard &lt;code&gt;checked&lt;/code&gt; and &lt;code&gt;indeterminate&lt;/code&gt; attributes, checkboxes and radio buttons have a &lt;code&gt;model&lt;/code&gt; bindable attribute that handles some pretty powerful use cases. By combining all these features, we can create a table with selectable rows and a select all checkbox at the top.&lt;/p&gt;

&lt;p&gt;First, we'll start by creating a basic checkbox and some radio buttons. Then, we'll use the &lt;code&gt;model&lt;/code&gt; binding to make the rows of a table selectable. Finally, we'll use the bindings to add a select all checkbox to the top of our table.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Checkbox
&lt;/h2&gt;

&lt;p&gt;The standard HTML &lt;code&gt;checked&lt;/code&gt; property is a boolean attribute. When you bind it to a variable, the result is a boolean value. Let's bind to a variable &lt;code&gt;canSort&lt;/code&gt; which toggles the ability to sort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"canSort"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  Enable Sorting
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This syncs the &lt;code&gt;canSort&lt;/code&gt; variable to the &lt;code&gt;checked&lt;/code&gt; attribute and state of the checkbox. When the checkbox is checked, &lt;code&gt;canSort === true&lt;/code&gt;. When it is unchecked, &lt;code&gt;canSort === false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Radio Button
&lt;/h2&gt;

&lt;p&gt;Radio buttons also have a checked property, but the default value is &lt;code&gt;on&lt;/code&gt; or &lt;code&gt;off&lt;/code&gt;. If we changed the example above to &lt;code&gt;type="radio"&lt;/code&gt;, we would have &lt;code&gt;canSort === 'on'&lt;/code&gt; or &lt;code&gt;canSort === 'off'&lt;/code&gt;. Radio buttons are more useful in conjuction with a &lt;code&gt;value&lt;/code&gt; binding. When &lt;code&gt;value&lt;/code&gt; is bound, the bound &lt;code&gt;checked&lt;/code&gt; variable will receive the bound &lt;code&gt;value&lt;/code&gt; when it is checked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"sorting"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; none
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"ascending"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"sorting"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; ascending
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"descending"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"sorting"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; descending
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This syncs &lt;code&gt;sorting&lt;/code&gt; to the value of the &lt;code&gt;value&lt;/code&gt; binding. When the "ascending" radio button is toggled, &lt;code&gt;sorting === 'ascending'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this case, it would be more useful to bind the &lt;code&gt;sorting&lt;/code&gt; variable to integers &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, and &lt;code&gt;-1&lt;/code&gt; so that we could use them in an &lt;code&gt;Array.sort&lt;/code&gt; method call; however, the &lt;code&gt;value&lt;/code&gt; binding is limited to strings! Aurelia includes a &lt;code&gt;model&lt;/code&gt; binding on checkboxes and radio buttons that works identically to the &lt;code&gt;value&lt;/code&gt; binding but supports all JavaScript values. Let's use that instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sortings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ascending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;descending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;Sorting:
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;repeat.for=&lt;/span&gt;&lt;span class="s"&gt;"sort of sortings"&lt;/span&gt; &lt;span class="na"&gt;if.bind=&lt;/span&gt;&lt;span class="s"&gt;"canSort"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"radio"&lt;/span&gt; &lt;span class="na"&gt;model.bind=&lt;/span&gt;&lt;span class="s"&gt;"sort.value"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"sorting"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; ${sort.label}
&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, when we toggle 'ascending', &lt;code&gt;sorting === 1&lt;/code&gt;, and likewise for the other radio buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting Items in an Array
&lt;/h2&gt;

&lt;p&gt;If you include the &lt;code&gt;model&lt;/code&gt; binding on a checkbox, then you can bind &lt;code&gt;checked&lt;/code&gt; to an array and it will add values to the array when checked and remove them when unchecked. This makes it easy to track a list of selected items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We define an array that will be bound to the `checked` binding of our selection checkboxes.&lt;/span&gt;
&lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="c1"&gt;// And we have an array of objects that will get added to and from the selection.&lt;/span&gt;
&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;repeat.for=&lt;/span&gt;&lt;span class="s"&gt;"item of items"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- When the checkbox is checked, the `selected` array will contain `item`. When unchecked, `item` will be removed from `selected`. --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"selected"&lt;/span&gt; &lt;span class="na"&gt;model.bind=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;${item.value}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  The Select All Checkbox
&lt;/h1&gt;

&lt;p&gt;Here's the trick that most people don't know about. Let's add a checkbox to the top of the table that will be (1) checked when all items are selected, (2) unchecked when no items are selected, and (3) indeterminate when some items are selected. &lt;code&gt;indeterminate&lt;/code&gt; is a boolean attribute, just like &lt;code&gt;checked&lt;/code&gt;, and therefore it can be bound just like any other attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="na"&gt;--&lt;/span&gt; &lt;span class="na"&gt;--&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="c"&gt;&amp;lt;!-- We want the checkbox to be checked when the selected array contains all the items in the items array.
            We can take a shortcut and just compare lengths. You can bind anything here so long as it is true when the
            two arrays are equal. Since this is an expression and not a value, the default two-way binding will not
            work since you cannot assign to an expression. So, we ask Aurelia for a one-way binding only. --&amp;gt;&lt;/span&gt;
          checked.one-way="selected.length === items.length"

          &lt;span class="c"&gt;&amp;lt;!-- We want the checkbox to be indeterminate when the selected array contains some but not all items in the
            items in array. Just like with the `checked` binding, we take the shortcut of comparing array lengths. Again
            you can bind anything here so long as its true when selected includes some but not all of the elements in
            items. Indeterminate is a one-way binding, so we can just use the standard bind syntax. --&amp;gt;&lt;/span&gt;
          indeterminate.bind="selected.length &amp;gt; 0 &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; selected.length &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;items.length&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;value&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now when we check checkboxes in our table the select all checkbox will update based on our selection. The select all checkbox does not yet add or remove items from the &lt;code&gt;selected&lt;/code&gt; array, though, so let's add that next. Since we are binding to expressions for both &lt;code&gt;checked&lt;/code&gt; and &lt;code&gt;indeterminate&lt;/code&gt;, it would be difficult to handle this behavior with a binding. Instead, let's handle it by listening for the &lt;code&gt;change&lt;/code&gt; event on our select all checkbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
          &lt;span class="na"&gt;checked.one-way=&lt;/span&gt;&lt;span class="s"&gt;"selected.length === items.length"&lt;/span&gt;
          &lt;span class="na"&gt;indeterminate.bind=&lt;/span&gt;&lt;span class="s"&gt;"selected.length &amp;gt; 0"&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="na"&gt;--&lt;/span&gt; &lt;span class="na"&gt;--&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="c"&gt;&amp;lt;!-- `$event.target`, the target of the event, is the checkbox. When checked, we want `selected` to contain
            all the items in `items`, or `items.slice()`. When unchecked, we want `selected` to be an empty array. --&amp;gt;&lt;/span&gt;
          change.delegate="selected = $event.target.checked ? items.slice() : []" /&amp;gt;
      &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;value&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, clicking the checkbox will select or deselect all the items in the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  As a Custom Element
&lt;/h2&gt;

&lt;p&gt;I don't love the syntax for the select all checkbox. Since I'm never using an array value for the &lt;code&gt;model&lt;/code&gt; binding in practice, I like to create a checkbox custom element that interprets an array-valued &lt;code&gt;model&lt;/code&gt; binding with the select all behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Checking this checkbox will add all the items from `items` to the `selected` array. Unchecking it will remove
  everything from `items`. Adding one but not all items from `items` to `selected` will set the checkbox state to
  indeterminate. --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;my-checkbox&lt;/span&gt; &lt;span class="na"&gt;checked.bind=&lt;/span&gt;&lt;span class="s"&gt;"selected"&lt;/span&gt; &lt;span class="na"&gt;model.bind=&lt;/span&gt;&lt;span class="s"&gt;"items"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have enough of these in a typical application that the time it takes writing a rock-solid component is justified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gist.run/?id=4ed6164d7edcf283f70ff1e6dd2164ef"&gt;Full Working Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/aurelia/aurelia/issues/447"&gt;Aurelia 2 Checkbox / Radio Button RFC&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/58359355/how-do-i-create-a-select-all-checkbox-when-i-have-an-empty-array-as-my-checked-b/58438010#58438010"&gt;StackOverflow question which inspired this post&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aurelia.io/docs/binding/checkboxes/"&gt;Aurelia Checkbox Binding Docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aurelia</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
