Skip to content

Commit

Permalink
fix: select support for plain options
Browse files Browse the repository at this point in the history
  • Loading branch information
czosel committed Feb 9, 2022
1 parent 2c6b957 commit 853f951
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 34 deletions.
25 changes: 4 additions & 21 deletions addon/components/validated-input/types/select.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,10 @@
</optgroup>
{{/each}}
{{else}}
{{#each @options as |opt|}}
{{#let
(if
(or @optionValuePath @optionTargetPath)
(get opt (or @optionValuePath @optionTargetPath))
opt
)
as |optionValue|
}}
<option selected={{eq optionValue @value}} value={{optionValue}}>{{#if
@optionLabelPath
}}
{{get opt @optionLabelPath}}
{{else if @optionValuePath}}
{{get opt @optionValuePath}}
{{else if @optionTargetPath}}
{{get opt @optionTargetPath}}
{{else}}
{{opt}}
{{/if}}</option>
{{/let}}
{{#each this.normalizedOptions as |opt|}}
<option selected={{eq opt.id @value}} value={{opt.id}}>
{{opt.label}}
</option>
{{/each}}
{{/if}}
</select>
42 changes: 36 additions & 6 deletions addon/components/validated-input/types/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@ export default class SelectComponent extends Component {
return this.hasPreGroupedOptions || this.args.groupLabelPath;
}

get hasPlainOptions() {
return typeof this.args.options[0] !== "object";
}

get normalizedOptions() {
// normalize options to common data structure, only for rendering
if (this.hasPlainOptions) {
return this.args.options.map((opt) => ({
id: opt,
label: opt,
}));
}
const valuePath = this.args.optionValuePath || this.args.optionTargetPath;
const labelPath = this.args.optionLabelPath;
return this.args.options.map((opt) => ({
id: valuePath ? opt[valuePath] : opt.id,
label: labelPath ? opt[labelPath] : opt.label,
...opt,
}));
}

get optionGroups() {
const groupLabelPath = this.args.groupLabelPath;
if (!groupLabelPath) {
Expand Down Expand Up @@ -72,6 +93,17 @@ export default class SelectComponent extends Component {
findOption(target) {
const targetPath = this.args.optionTargetPath;
const valuePath = this.args.optionValuePath || targetPath;

const getValue = (item) => {
if (valuePath) {
return String(item[valuePath]);
}
if (typeof item === "object") {
return String(item.id);
}
return String(item);
};

let options = this.args.options;

//flatten pre grouped options
Expand All @@ -85,19 +117,17 @@ export default class SelectComponent extends Component {
.call(target.options, (option) => option.selected)
.map((option) => option.value);

const foundOptions = options.filter((item) =>
selectedValues.includes(`${valuePath ? item[valuePath] : item}`)
);
const foundOptions = options.filter((item) => {
return selectedValues.includes(getValue(item));
});
if (targetPath) {
return foundOptions.map((item) => item[targetPath]);
}
return foundOptions;
}

//single select
const foundOption = options.find(
(item) => `${valuePath ? item[valuePath] : item.value}` === target.value
);
const foundOption = options.find((item) => getValue(item) === target.value);
if (targetPath) {
return foundOption[targetPath];
}
Expand Down
58 changes: 51 additions & 7 deletions tests/integration/components/validated-input/types/select-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ module(

test("it renders", async function (assert) {
this.set("options", [
{ key: 1, label: 1 },
{ key: 2, label: 2 },
{ id: 1, label: 1 },
{ id: 2, label: 2 },
]);

await render(
Expand All @@ -23,6 +23,25 @@ module(
assert.dom("option:first-child").hasProperty("selected", true);
});

test("it supports plain (non-object) options", async function (assert) {
assert.expect(6);
this.set("options", ["foo", "bar"]);

this.set("update", (value) => {
assert.strictEqual(value, "bar");
});
await render(
hbs`<ValidatedInput::Types::Select @options={{this.options}} @update={{this.update}} />`
);

assert.dom("select").exists();
assert.dom("option").exists({ count: 2 });
assert.dom("option:first-child").hasProperty("selected", true);
await select("select", "bar");
assert.dom("option:first-child").hasProperty("selected", false);
assert.dom("option:last-child").hasProperty("selected", true);
});

test("it works with solitary optionTargetPath property", async function (assert) {
assert.expect(2);
this.set("options", [
Expand All @@ -38,7 +57,7 @@ module(
hbs`<ValidatedInput::Types::Select @options={{this.options}} @update={{this.update}} @optionTargetPath="key" />`
);

assert.dom("option:first-child").hasText("111");
assert.dom("option:first-child").hasText("firstOption");
await select("select", "222");
});

Expand Down Expand Up @@ -130,18 +149,43 @@ module(
});

test("multiselect is working", async function (assert) {
assert.expect(3);
this.set("options", ["1", "2"]);
assert.expect(4);
this.set("options", [
{ id: 1, label: "label 1" },
{ id: 2, label: "label 2" },
{ id: 3, label: "label 3" },
]);
this.set("update", (values) => {
assert.deepEqual(values, [
{ id: 1, label: "label 1" },
{ id: 3, label: "label 3" },
]);
});

await render(
hbs`<ValidatedInput::Types::Select @options={{this.options}} @multiple={{true}} @update={{this.update}} />`
);

await select("select", ["1", "3"]);
assert.dom("option:first-child").hasProperty("selected", true);
assert.dom("option:nth-child(2)").hasProperty("selected", false);
assert.dom("option:last-child").hasProperty("selected", true);
});

test("multiselect is working with plain options", async function (assert) {
assert.expect(4);
this.set("options", ["1", "2", "3"]);
this.set("update", (values) => {
assert.deepEqual(values, this.options);
assert.deepEqual(values, ["1", "3"]);
});

await render(
hbs`<ValidatedInput::Types::Select @options={{this.options}} @multiple={{true}} @update={{this.update}} />`
);

await select("select", this.options);
await select("select", ["1", "3"]);
assert.dom("option:first-child").hasProperty("selected", true);
assert.dom("option:nth-child(2)").hasProperty("selected", false);
assert.dom("option:last-child").hasProperty("selected", true);
});

Expand Down

0 comments on commit 853f951

Please sign in to comment.