Hi I am new to ember and trying to create a dropdown list using .
Is there a way where I can access the selected item in drop down list in ember via component? Give me a short example.
Thanks in advance.
Hi I am new to ember and trying to create a dropdown list using .
Is there a way where I can access the selected item in drop down list in ember via component? Give me a short example.
Thanks in advance.
There are a number of ways to write a select component but the absolute simplest way would be like this:
// app/components/my-select.hbs
<select {{on "change" (pick "target.value" @onChange)}}>
{{#each @options as |theOption|}}
<option value={{theOption}} selected={{eq theOption @value}}>{{theOption}}</option>
{{/each}}
</select>
So whatâs going on here?
<select >
tag, thatâs just standard HTML.{{on ...}}
modifier. This sets up an onchange handler and delegates the actual handling to the onChange
argument of the component (so whatever is rendering the component can set the value, this component shouldnât do any mutations itself)option
tag, and only mark the option tag as selected if @value
is equal to the current option.and then you could render it like this:
<MySelect
@value={{this.selectedOption}}
@options={{this.options}}
@onChange={{set this "selectedOption"}}
/>
Here weâre binding the local âselectedOptionâ property to the @value
argument of the select. Next weâre passing in options (I assumed theyâre at this.options
but you could pass them in with any alias of course). Lastly weâre setting up a change handler. The set
helper (see note below) is just an easy way of saying "set the value we receive to the new value of this.selectedOption
.
Note that Iâm using helpers from three different helper libraries here:
{{pick ...}}
from ember-composable-helpers{{eq ...}}
from ember-truth-helpers{{set ...}}
from ember-set-helperNone of those are necessary but they make the example above the most compact and javascript-free. If you added a javascript class or two you could get the same effect without addons or writing extra helpers.
For the sake of completeness Iâll add snippets for a no-addons version below:
// app/components/my-select.hbs
<select {{on "change" this.onChange}}>
{{#each @options as |option|}}
<MyOption @value={{option}} @selectValue={{@value}} />
{{/each}}
</select>
// app/components/my-select.js
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class MySelectComponent extends Component {
@action onChange(event) {
this.args.onChange(event.target.value);
}
}
// app/components/my-option.hbs
<option value={{@value}} selected={{this.selected}}>{{@value}}</option>
// app/components/my-option.js
import Component from '@glimmer/component';
export default class MyOptionComponent extends Component {
get isSelected() {
this.args.value === this.args.selectValue;
}
}
Hi thanks for your help it is very helpful in understanding. I am very new to ember/ javascript. I also need help on where to define the drop down list options like âYesâ and âNoâ. Thanks in advance.
Sure thing. As with anything there a lot of ways you could do it, but Iâll break it down and give you a couple examples.
First, weâre making the assumption that weâre using the component we created above, to simplify things. Second, there are at least 3 ways you could create/bind options and give them to the component:
The simplest option is to create/bind the options via the {{array }}
helper. This remove the need to use javascript entirely. To do that you could render your component like this:
<MySelect
@value={{this.selectedOption}}
@options={{array "Yes" "No"}}
@onChange={{set this "selectedOption"}}
/>
The âarrayâ helper takes a list of arguments and returns an array, so the above invocation is simply passing ["Yes", "No"]
to the select as the options
arg. This allows unlimited options to be passed and is also highly declarative.
Controllers will eventually go away so you may as well start thinking in component terms and skip to #3 but controllers still have their place so itâs still worth showing. Your controller should have the same name as your route and look something like this:
// app/controllers/my-route-name.js
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class MyRouteNameController extends Controller {
@tracked selectedOption = null;
options = ["Yes", "No"];
@action optionChanged(newOption) {
this.selectedOption = newOption;
}
}
// app/templates/my-route-name.hbs
<MySelect
@value={{this.selectedOption}}
@options={{this.options}}
@onChange={{this.optionChanged}}
/>
<div>The currently selected option is: {{this.selectedOption}}</div>
Whatâs going on here? Weâve added two properties to the controller, and one action (you could omit the action if you use the set
helper like I demonstrated earlier).
The first property, selectedOption
, is tracked
meaning it will auto-update any consumers (including bound template values) if it changes. This is important because the select will be changing this value.
Next we have the options
property, which of course holds your options. In this case it doesnât need to be tracked because itâs static and wonât change. The options are always the same.
Last, we have the action optionChanged
. This handles updating selectedOption
every time the option changes (and again you could omit this action if you use the set helper that I mentioned previously).
Finally weâre rendering the selected option at the bottom so you can see it live update as you change the select value. Neato!
If youâre rendering the select inside another component itâs going to look almost exactly the same as the controller version, just in a different file:
// app/components/my-form.js
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class MyFormComponent extends Component {
@tracked selectedOption = null;
options = ["Yes", "No"];
@action optionChanged(newOption) {
this.selectedOption = newOption;
}
}
// app/components/my-form.hbs
<MySelect
@value={{this.selectedOption}}
@options={{this.options}}
@onChange={{this.optionChanged}}
/>
<div>The currently selected option is: {{this.selectedOption}}</div>
Literally the same thing, just note that itâs a component backing class holding the properties and action instead of a controller and the select is rendered in a component template and not a route template
Being a tailwindCss fun!! I go with some like GitHub - tailwindlabs/headlessui: Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS. Go! tailwindCss with JIT