all files / addon/components/ polaris-choice-list.js

100% Statements 24/24
100% Branches 14/14
83.33% Functions 5/6
100% Lines 23/23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164                      22× 22×                                                                                                                                                                                                                         22×                                            
import Component from '@ember/component';
import { get, computed } from '@ember/object';
import { guidFor } from '@ember/object/internals';
import { isEmpty } from '@ember/utils';
import ObjectProxy from '@ember/object/proxy';
import layout from '../templates/components/polaris-choice-list';
 
// Wrapper class to add an `isSelected` flag to the supplied choices.
const CheckedChoice = ObjectProxy.extend({
  selected: null,
 
  isSelected: computed('content.value', 'selected.[]', function() {
    const selected = this.get('selected');
    return selected && selected.indexOf(this.get('value')) > -1;
  }).readOnly(),
});
 
/**
 * Polaris choice list component.
 * See https://polaris.shopify.com/components/forms/choice-list
 */
export default Component.extend({
  tagName: 'fieldset',
  classNames: ['Polaris-ChoiceList'],
  classNameBindings: ['titleHidden:Polaris-ChoiceList--titleHidden'],
 
  layout,
 
  /**
   * Label for list of choices
   *
   * @property title
   * @public
   * @type {string}
   * @default null
   */
  title: null,
 
  /**
   * Collection of choices
   *
   * Each choice can have these properties:
   *
   *  - value
   *  - label
   *  - disabled
   *  - helpText
   *  - renderChildren (not implemented yet)
   *
   * @property choices
   * @public
   * @type {Array}
   * @default null
   */
  choices: null,
 
  /**
   * Collection of selected choices
   *
   * @property selected
   * @public
   * @type {Array}
   * @default null
   */
  selected: null,
 
  /**
   * Name for form input
   *
   * @property name
   * @public
   * @type {string}
   * @default null
   */
  name: null,
 
  /**
   * Allow multiple selections
   *
   * @property allowMultiple
   * @public
   * @type {boolean}
   * @default false
   */
  allowMultiple: false,
 
  /**
   * Toggles display of the title
   *
   * @property titleHidden
   * @public
   * @type {boolean}
   * @default false
   */
  titleHidden: false,
 
  /**
   * Callback when the selected choices change
   *
   * @property onChange
   * @public
   * @type {function}
   * @default noop
   */
  onChange() {},
 
  /*
   * Internal properties.
   */
  controlComponent: computed('allowMultiple', function() {
    return this.get('allowMultiple') ? 'polaris-checkbox' : 'polaris-radio-button';
  }).readOnly(),
 
  finalName: computed('name', 'allowMultiple', function() {
    let { name, allowMultiple } = this.getProperties('name', 'allowMultiple');
 
    if (isEmpty(name)) {
      name = guidFor(this);
    }
 
    if (allowMultiple) {
      name = `${name}[]`;
    }
 
    return name;
  }).readOnly(),
 
  checkedChoices: computed('choices.[]', function() {
    const choices = this.get('choices') || [];
    const selected = this.get('selected');
 
    return choices.map((choice) => {
      return CheckedChoice.create({
        content: choice,
        selected,
      });
    });
  }).readOnly(),
 
  /*
   * Actions.
   */
  actions: {
    updateSelectedChoices(choice, checked) {
      const value = get(choice, 'value');
      let updatedSelectedChoices;
 
      if (this.get('allowMultiple')) {
        const selected = this.get('selected');
        if (checked) {
          updatedSelectedChoices = [...selected, value];
        } else {
          updatedSelectedChoices = selected.filter((selectedChoice) => selectedChoice !== value);
        }
      } else {
        updatedSelectedChoices = [ value ];
      }
 
      return this.get('onChange')(updatedSelectedChoices, this.get('name'));
    },
  }
});