my-own-select
v1.1.4
Published
Una select custom pronta all'uso in tutti i progetti frontend!
Downloads
289
Maintainers
Readme
my-own-select
my-own-select
is a highly customizable dropdown select component built using the customElements
API. It is compatible with both ReactJS and Angular, and it allows for in-depth customization of the dropdown appearance and behavior. my-own-select
offers a flexible structure, allowing you to insert HTML tags, components, and styled elements as options within the select dropdown.
Installation
You can install my-own-select
via npm:
npm install my-own-select
Usage
To use my-own-select
in your project, simply include it as a custom HTML element. Below is an example of how to use it:
<my-own-select>
<p>First option</p>
<h1>Second option</h1>
<Component></Component>
</my-own-select>
get Selected value:
in order to get selected value of your option, it's possible to set a custom attribute on sigle item called option-value
which can be different rather than text contained inside your html tag:
<my-own-select>
<p option-value="foo">First option</p>
<h1 option-value="bar">Second option</h1>
<div>
<p>Third</p>
<h1>option</bar>
</div>
<Component></Component>
</my-own-select>
the value is provided by a custom event called selection
which can be detected also a simple eventListener (depends by technology do you want to use).
For the above example, along the selection
event, for the first item of select will be passed foo
value, for the second one will be passed bar
. For third element instead, because the attribute option-value
is not set, will passed innerText
found in DOM element
<my-own-select>
<p option-value="foo">First option</p> <!--WILL GET 'foo' -->
<h1 option-value="bar">Second option</h1> <!--WILL GET 'bar' -->
<div>
<p>Third</p>
<h1>option</bar>
</div> <!--WILL GET 'Third\noption' -->
<Component></Component>
</my-own-select>
placeholder options:
set a placeholder option adding option-placeholder
attribute to an option:
<my-own-select>
<div option-placeholder>Hello</div>
<div>World</div>
</my-own-select>
the option to which the option-placeholder
attribute is applied will always be placed in first position compared to the other options and it's value is always an empty string, even if on same option is applied also option-value
attribute
DISABLED
to set disabled state:
<my-own-select disabled>
<div>Hello</div>
<div>World!</div>
</my-own-select>
disabled styles:
for css disabled state:
my-own-select::part(select):disabled{ background: red; }
FORM COMPATIBILITY
my-own-select is fully compatible with form context:
<form>
<input type="text" />
<my-own-select>
<p>Hello</p>
<div>World!</div>
</my-own-select>
<button type="submit">Send</button>
</form>
for testing form value:
document.querySelector('form')?.addEventListener('submit', (event:any) => {
event.preventDefault();
let values = Array.prototype.slice.call(event.target.elements).filter(e => e.type !== 'submit').map(e => e.value);
console.log(values.join(','));
})
React (Javascript or Typescritpt)
For ReactJS, ensure you import and use the my-own-select
component as a custom element within your JSX code. You may need to register the component to ensure it works as expected:
import 'my-own-select';
function App() {
const selectRef = React.useRef();
React.useEffect(() => {
const handleSelection = (event) => {
console.log("Selected option:", event.detail);
};
const currentSelect = selectRef.current;
currentSelect.addEventListener("selection", handleSelection);
return () => currentSelect.removeEventListener("selection", handleSelection);
}, []);
return (
<my-own-select ref={selectRef}>
<p>First option</p>
<h1>Second option</h1>
<MyComponent />
</my-own-select>
);
}
Angular
For Angular projects, you may need to allow custom elements within your module by configuring CUSTOM_ELEMENTS_SCHEMA
:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import 'my-own-select';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
Then, you can use my-own-select
in your Angular templates and listen for the selection
event:
<my-own-select (selection)="onSelection($event)">
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
In your Angular component, define the onSelection
method:
export class AppComponent {
onSelection(event: CustomEvent) {
console.log("Selected option:", event.detail);
}
}
form compatibility with Angular
in order to render my-own-select fully compatible with reactiveForms
or forms
modules you have to create a value accessor for this new element. The following code is a proposal directive you can use inside your project to work with my-own-select and ReactiveFormsModule
or FormsModule
in your Angular application:
custom directive:
import { Directive, ElementRef, forwardRef, HostListener } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Directive({
selector: 'my-own-select[formControlName],my-own-select[formControl],my-own-select[ngModel]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomFormControlDirective),
multi: true
}
]
})
export class CustomFormControlDirective implements ControlValueAccessor {
private _value: any = '';
constructor(private elementRef: ElementRef) {}
// get "selection" custom event
@HostListener('selection', ['$event'])
onSelectionChange(event: CustomEvent) {
const value = event.detail.value;
this._value = value;
this.onChange(value);
this.onTouched();
}
// Write value
writeValue(value: any): void {
this._value = value;
if (this.elementRef.nativeElement) {
this.elementRef.nativeElement.setAttribute('value', value);
}
}
// Register change function
registerOnChange(fn: any): void {
this.onChange = fn;
}
// Register touched function
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
// Callback for changes
onChange: any = () => {};
onTouched: any = () => {};
// Handle disabled state
setDisabledState?(isDisabled: boolean): void {
if (this.elementRef.nativeElement) {
this.elementRef.nativeElement.disabled = isDisabled;
}
}
}
usage custom directive:
- in your typescript file:
...
import { CustomFormControlDirective } from './directives/custom-form-control';
@Component({
selector: 'app-root',
imports: [ReactiveFormsModule, CustomFormControlDirective],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class YourComponent {
protected fb = inject(FormBuilder);
form:FormGroup<any> | undefined;
constructor(){
this.form = this.fb?.group({
'my-select': ['', Validators.required],
'text': ['', Validators.required]
})
}
log(value:any){
console.log(value);
}
}
- in your template:
<form [formGroup]="form" (ngSubmit)="log(form.value)">
<input type="text" formControlName="text" >
<my-own-select formControlName="my-select" >
<div>Hello</div>
<div option-value="world">WOOORLD!</div>
</my-own-select>
<button [disabled]="form.invalid">Send</button>
</form>
Vue (Javascript or Typescritpt)
For Vue projects, you can use my-own-select
in your scripts:
<script setup lang="ts">
import "my-own-select";
const onSelection = (event: CustomEvent<any>) => {
console.log(event);
};
</script>
and listen for the selection
event:
<my-own-select @selection="onSelection">
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
Solid (Javascript or Typescritpt)
For Solid projects, you can import my-own-select
:
import 'my-own-select';
and use it in your JSX:
<my-own-select>
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
for handle selection event:
const onSelection = (event:CustomEvent<any>) => {
console.log(event);
}
<my-own-select on:selection={onSelection}>
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
Qwik
For Qwik, ensure you import and use the my-own-select
component as a custom element within your JSX code. You may need to register the component to ensure it works as expected:
import 'my-own-select';
export const App = component$(() => {
useOn('selection', $((event: CustomEvent) => {
console.log(event.detail);
}));
return (
<my-own-select window:selection={handleSelection$} >
<p option-value="hello">First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
);
});
Svelte (Javascript, Typescritpt and SvelteKit)
For Svelte projects, you can use my-own-select
in your scripts:
<script setup lang="ts">
import "my-own-select";
const onSelection = (event: CustomEvent<any>) => {
console.log(event);
};
</script>
and listen for the selection
event:
<my-own-select on:selection={onSelection}>
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
Preact
For Preact projects, you can import my-own-select
:
import 'my-own-select';
and use it in your JSX:
<my-own-select>
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
for handle selection event:
const onSelection = (event:CustomEvent<any>) => {
console.log(event);
}
<my-own-select onselection={onSelection}>
<p>First option</p>
<h1>Second option</h1>
<my-component></my-component>
</my-own-select>
CSS Customization
my-own-select
provides parts that can be styled via the ::part()
selector. This allows you to fully customize the dropdown’s appearance:
my-own-select
provides parts that can be styled via the ::part()
selector. This allows you to fully customize the dropdown’s appearance:
Select container: Customize the main select element.
my-own-select::part(select) { my-own-select::part(select) { /* Add your styles here */ background-color: lightgray; border: 1px solid #ccc; padding: 10px; }
Options container: Style the container holding all options.
my-own-select::part(itemsContainer) { /* Add your styles here */ background-color: white; border: 1px solid #ccc; max-height: 200px; overflow-y: auto; }
Single option item: Customize individual options.
my-own-select::part(item) { /* Add your styles here */ padding: 8px; cursor: pointer; } my-own-select::part(item-selected) { /* Selected item */ background-color: #f0f0f0; }
Custom Event: selection
When an option is selected, my-own-select
emits a custom event called selection
. This can be intercepted in both ReactJS and Angular:
When an option is selected, my-own-select
emits a custom event called selection
. This can be intercepted in both ReactJS and Angular:
- ReactJS: Use a
ref
to attach an event listener tomy-own-select
and handle the selection event. - Angular: Bind directly to the
(selection)
event on themy-own-select
tag. - Vue: Bind directly to the
@selection
event on themy-own-select
tag. - Solid: Bind directly to the
on:selection
event on themy-own-select
tag. - Qwik: Use a
useOn
to attach an event listener tomy-own-select
and handle the selection event. - Svelte: Bind directly to the
on:selection
event on themy-own-select
tag. - Preact: Bind directly to the
onselection
event on themy-own-select
tag.
Custom Arrow
You can customize the arrow of your select simply writing this:
<my-own-select >
<p>First option</p>
<h1>Second option</h1>
<img slot="arrowImg" src="yourUrl" alt="yourAlt" />
</my-own-select>
everywhere in your select, event at begin or in the middle of your options:
<my-own-select >
<p>First option</p>
<img slot="arrowImg" src="yourUrl" alt="yourAlt" />
<h1>Second option</h1>
</my-own-select>
- ReactJS: Use a
ref
to attach an event listener tomy-own-select
and handle the selection event. - Angular: Bind directly to the
(selection)
event on themy-own-select
tag. - Vue: Bind directly to the
@selection
event on themy-own-select
tag. - Solid: Bind directly to the
on:selection
event on themy-own-select
tag. - Qwik: Use a
useOn
to attach an event listener tomy-own-select
and handle the selection event. - Svelte: Bind directly to the
on:selection
event on themy-own-select
tag. - Preact: Bind directly to the
onselection
event on themy-own-select
tag.
Custom Arrow
You can customize the arrow of your select simply writing this:
<my-own-select >
<p>First option</p>
<h1>Second option</h1>
<img slot="arrowImg" src="yourUrl" alt="yourAlt" />
</my-own-select>
everywhere in your select, event at begin or in the middle of your options:
<my-own-select >
<p>First option</p>
<img slot="arrowImg" src="yourUrl" alt="yourAlt" />
<h1>Second option</h1>
</my-own-select>
Compatibility
my-own-select
is built with the customElements
API, making it natively compatible across modern browsers. It integrates seamlessly with popular frontend frameworks like ReactJS and Angular.
Contributing
If you'd like to contribute to my-own-select
, please submit an issue or a pull request on our GitHub repository. Contributions, bug reports, and feature suggestions are welcome!
License
This project is licensed under the MIT License. See the LICENSE file for more details.
Happy coding with my-own-select
!
Authors
Badges
Add badges from somewhere like: shields.io
Contributing
Contributions are always welcome!
See contributing.md
for ways to get started.
Please adhere to this project's code of conduct
.