{"id":32173167,"url":"https://github.com/maxmarcon/live_select","last_synced_at":"2026-02-22T11:06:57.486Z","repository":{"id":55273179,"uuid":"504958756","full_name":"maxmarcon/live_select","owner":"maxmarcon","description":"Dynamic (multi)selection field for LiveView","archived":false,"fork":false,"pushed_at":"2025-11-28T11:49:05.000Z","size":8711,"stargazers_count":243,"open_issues_count":18,"forks_count":58,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-11-30T18:10:41.465Z","etag":null,"topics":["component","daisyui","dropdown-menus","elixir","form-input","liveview","multiselect","tailwindcss","web-forms"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/live_select","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxmarcon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-06-18T21:58:48.000Z","updated_at":"2025-11-28T11:46:58.000Z","dependencies_parsed_at":"2023-09-24T22:16:22.629Z","dependency_job_id":"6c0402e7-8eee-4448-8437-da54a4743ede","html_url":"https://github.com/maxmarcon/live_select","commit_stats":{"total_commits":595,"total_committers":10,"mean_commits":59.5,"dds":"0.031932773109243695","last_synced_commit":"b2707dddf6327c39a7911b74a6a5a5061f99ec76"},"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/maxmarcon/live_select","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmarcon%2Flive_select","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmarcon%2Flive_select/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmarcon%2Flive_select/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmarcon%2Flive_select/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxmarcon","download_url":"https://codeload.github.com/maxmarcon/live_select/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxmarcon%2Flive_select/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29710317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T10:34:24.778Z","status":"ssl_error","status_checked_at":"2026-02-22T10:32:23.200Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","daisyui","dropdown-menus","elixir","form-input","liveview","multiselect","tailwindcss","web-forms"],"created_at":"2025-10-21T18:50:12.115Z","updated_at":"2026-02-22T11:06:57.446Z","avatar_url":"https://github.com/maxmarcon.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LiveSelect\n\n[![Hex](https://img.shields.io/hexpm/v/live_select.svg)](https://hex.pm/packages/live_select)\n[![Hexdocs](https://img.shields.io/badge/-docs-green)](https://hexdocs.pm/live_select)\n[![Elixir CI](https://github.com/maxmarcon/live_select/actions/workflows/elixir.yml/badge.svg)](https://github.com/maxmarcon/live_select/actions/workflows/elixir.yml)\n\nDynamic (multi)selection field for LiveView.\n\n`LiveSelect` is a LiveView component that implements a dynamic selection field with a dropdown. The content of the\ndropdown is filled by your LiveView as the user types. This allows you to easily create an \ninterface for search-like functionalities with type-ahead. `LiveSelect`s features include:\n\n* Single as well as multiple selection\n* Options to configure the behaviour, such as minimum number of characters that trigger an update or the maximum number of selectable options\n* Default styles for daisyUI and tailwindcss, which are fully customizable and can be completely overridden if needed\n* Ability to customize the rendered HTML for dropdown entries and tags using slots.\n\n### [Try it in the showcase app](https://live-select.fly.dev/) 🔬\n\n### Single selection (single mode)\n\n![DEMO](https://raw.githubusercontent.com/maxmarcon/live_select/main/priv/static/images/demo_single.gif)\n\n### Multiple selection (tags mode)\n\n![DEMO](https://raw.githubusercontent.com/maxmarcon/live_select/main/priv/static/images/demo_tags.gif)\n\n### Multiple selection (quick_tags mode)\n\n![DEMO](https://raw.githubusercontent.com/maxmarcon/live_select/main/priv/static/images/demo_quick_tags.gif)\n\n## Usage Example 🧭\n\n_Template:_\n\n```elixir\n  \u003c.form for={@form} phx-change=\"change\"\u003e\n    \u003c.live_select field={@form[:city_search]} /\u003e \n  \u003c/.form\u003e\n```\n\n**NOTE:** If your form is implemented in a LiveComponent, add `phx-target={@myself}`, like this:\n\n```elixir\n  \u003c.live_select field={@form[:city_search]} phx-target={@myself} /\u003e\n```\n\n_In the LiveView or LiveComponent that's the target of your form events:_\n\n  ```elixir\n  @impl true\n  def handle_event(\"live_select_change\", %{\"text\" =\u003e text, \"id\" =\u003e live_select_id}, socket) do \n    cities = City.search(text)\n    # cities = [ \n    # {\"New York City\", [-74.00597,40.71427]}, \n    # {\"New Kingston\", [-76.78319,18.00747]}, \n    # ... \n    # ]\n\n    send_update(LiveSelect.Component, id: live_select_id, options: cities)\n    \n    {:noreply, socket}\n  end\n\n  @impl true\n  def handle_event(\n        \"change\",\n        %{\"my_form\" =\u003e %{\"city_search_text_input\" =\u003e city_name, \"city_search\" =\u003e city_coords}},\n        socket\n      ) do\n    IO.puts(\"You selected city #{city_name} located at: #{city_coords}\")\n\n    {:noreply, socket}\n  end  \n  ```\n\nRefer to the [module documentation](https://hexdocs.pm/live_select/LiveSelect.html) for the details, and\ncheck out the [cheatsheet](https://hexdocs.pm/live_select/cheatsheet.html) for some useful tips.\n\n## Installation 📦\n\nTo install, add this to your dependencies:\n\n```elixir\n[\n    {:live_select, \"~\u003e 1.0\"}\n]\n```\n\n## Javascript hooks 🪝\n\n`LiveSelect` relies on Javascript hooks to work. You need to add `LiveSelect`'s hooks to your live socket.\n`LiveSelect` distributes its Javascript code (a single file) in the same way as LiveView, by including an\nnpm package as part of its hex package.\n\nTo include `LiveSelect`'s hooks, add this to your `app.js` file:\n\n```javascript\nimport live_select from \"live_select\"\n\n// if you don't have any other hooks:\nlet liveSocket = new LiveSocket(\"/live\", Socket, {params: {_csrf_token: csrfToken}, hooks: live_select})\n\n// if you have other hooks:\nconst hooks = {\n    MyHook: {\n        // ...\n    },\n    ...live_select\n}\nlet liveSocket = new LiveSocket(\"/live\", Socket, {params: {_csrf_token: csrfToken}, hooks})\n```\n\n### If you're using Webpack or another NPM-based builder\n\nIf you're using an npm-based builder such as Webpack, you will need to add `LiveSelect` to the list of your dependencies in your `package.json` (just as you did with LiveView):\n\n```js\n{\n  \"dependencies\": {\n    \"phoenix\": \"file:../deps/phoenix\",\n    \"phoenix_html\": \"file:../deps/phoenix_html\",\n    \"phoenix_live_view\": \"file:../deps/phoenix_live_view\",\n    \"live_select\":  \"file:../deps/live_select\" // \u003c-- add this line, and add an extra \"../\" if you're in an umbrella app\n  }\n}\n```\n\nAnd then run `npm install` from your `assets` folder. You will also need to run `npm install --force live_select`\nwhenever you update the `LiveSelect` hex package in order to get the latest JS code.\n\n## Styling 🎨\n\n`LiveSelect` supports 3 styling modes:\n\n* `tailwind`: uses standard tailwind utility classes (the default)\n* `daisyui`: uses [daisyUI](https://daisyui.com/) classes.\n* `none`: no styling at all.\n\nThe choice of style is controlled by the `style` option\nin [live_select/1](https://hexdocs.pm/live_select/LiveSelect.html#live_select/1).\n`tailwind` and `daisyui` styles come with sensible defaults which can be selectively extended or completely overridden.\n\nRefer to the [Styling section](https://hexdocs.pm/live_select/styling.html) for further details.\n\n\u003e ⚠️ **Attention**\n\u003e \n\u003e Please note the different paths for a standalone or umbrella app.\n\n### tailwind v3\n\nIf you're using `tailwind` or `daisyui` styles, you need to add one of the following lines to the `content` section in\nyour `tailwind.config.js`:\n\n```javascript\nmodule.exports = {\n    content: [\n        //...\n        '../deps/live_select/lib/live_select/component.*ex', // \u003c-- for a standalone app\n        '../../../deps/live_select/lib/live_select/component.*ex' // \u003c-- for an umbrella app\n    ]\n    //..\n}\n```\n\n### tailwind v4\n\nIf you are using `tailwind v4+` and are not using a `tailwind.config.js` file you instead need to add the relevant `@source` directive to your `app.css` file:\n\n```css\n@source \"../../deps/live_select/lib/live_select/component.*ex\" /* for a standalone app */\n@source \"../../../../deps/live_select/lib/live_select/component.*ex\" /* for an umbrella app */\n```\n\n\n\n\n## Showcase app 🎪\n\nThe repository includes a showcase app that you can use to experiment with the different options and parameters\nfor `LiveSelect`.\nThe showcase app is available [here](https://live-select.fly.dev/).\n\nTo start the showcase app locally, simply run:\n\n```\nmix setup\nPORT=4001 mix phx.server\n```\n\nfrom within the cloned repository. The app will be available at http://localhost:4001. The showcase app allows you to\nquickly experiment with options and styles, providing an easy way to fine tune your `LiveSelect` component. The app also\nshows the messages and events that your `LiveView` receives. For each event or message, the app shows the function head\nof the callback that your LiveView needs to implement in order to handle the event.\n\n## Contribute 🤝\n\nContributions are very welcome! However, if you want do add a new feature please discuss it first by creating an issue so we can all agree that it's needed. \nAlso, it's important to add a test that covers it. If you don't know how to write the test or need guidance,\nI'm happy to help.\n\nUse `mix test` to run the entire test suite, which is subdivided into 3 main files:\n\n* `test/live_select/component_test.exs` - everything that can be tested by rendering the component statically\n* `test/live_select_test.exs` - tests for `single` mode that require a running LiveView \n* `test/live_select_tags_test.exs` - tests for `tags` mode that require a running LiveView\n* `test/live_select_quick_tags_test.exs` - tests for `quick_tags` mode that require a running LiveView\n\nTests that require a LiveView use the showcase app as the parent LiveView.\n\n## Roadmap 🛣️\n\n- [X] Add `package.json` to enable `import live_select from \"live_select\"`\n- [X] Make sure component classes are included by tailwind\n- [X] Enable custom styling\n- [X] Rename LiveSelect.render to live_select\n- [X] Customizable placeholder\n- [X] Enable configuration of styles in the showcase app\n- [X] Add support for vanilla tailwind styles\n- [X] Enable multiple selection mode\n- [X] Expose as function component (and drop LV 0.17 support)\n- [X] Add cheatsheet\n- [X] Additional multiple selection mode \n- [ ] Add section to document testing strategies\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmarcon%2Flive_select","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxmarcon%2Flive_select","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxmarcon%2Flive_select/lists"}