{"id":27193056,"url":"https://github.com/schrockwell/live_assign","last_synced_at":"2026-03-08T17:34:15.157Z","repository":{"id":53266269,"uuid":"521100514","full_name":"schrockwell/live_assign","owner":"schrockwell","description":"State management conventions for LiveView","archived":false,"fork":false,"pushed_at":"2022-09-10T00:19:03.000Z","size":136,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-20T21:09:17.260Z","etag":null,"topics":["elixir","liveview","phoenix"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schrockwell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-04T02:44:37.000Z","updated_at":"2024-08-06T03:58:08.000Z","dependencies_parsed_at":"2022-08-13T02:30:50.633Z","dependency_job_id":null,"html_url":"https://github.com/schrockwell/live_assign","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schrockwell%2Flive_assign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schrockwell%2Flive_assign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schrockwell%2Flive_assign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schrockwell%2Flive_assign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schrockwell","download_url":"https://codeload.github.com/schrockwell/live_assign/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248091222,"owners_count":21046236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["elixir","liveview","phoenix"],"created_at":"2025-04-09T18:46:25.237Z","updated_at":"2026-03-08T17:34:15.128Z","avatar_url":"https://github.com/schrockwell.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LiveAssign\n\n![Test Status](https://github.com/schrockwell/live_assign/actions/workflows/elixir.yml/badge.svg)\n[![Module Version](https://img.shields.io/hexpm/v/live_assign.svg)](https://hex.pm/packages/live_assign)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-purple.svg)](https://hexdocs.pm/live_assign/)\n[![License](https://img.shields.io/hexpm/l/live_assign.svg)](https://github.com/schrockwell/live_assign/blob/master/LICENSE)\n\nLiveAssign improves state management by sprinkling functionality on top of Phoenix LiveView.\n\nIt doesn't _replace_ the LiveView way of doing things, but instead _augments_ it with conventions. LiveAssign can be added to any view or component without affecting existing functionality, and its features can be opted-in as they are needed.\n\nCombine it with [LiveEvent](https://hexdocs.pm/live_event/) for an altogether improved component-building experience.\n\nLiveViews and LiveComponents both gain:\n\n- **State** assigns which are defined in the module\n- **Reactive functions** that are automatically invoked upon state changes\n- **Runtime checks** with developer-friendly error messages\n\nLiveComponents also gain additional functionality:\n\n- **Props** which are assigns that are strictly passed in to the component\n- **Slot** props to represent component slots\n- **Event** props that integrate with [LiveEvent](https://hexdocs.pm/live_event/)\n\nHere are a couple examples showing off these features. For complete details, please reference [the docs](https://hexdocs.pm/live_assign/).\n\n## LiveComponent Example\n\n```elixir\ndefmodule MyAppWeb.UserProfileComponent do\n  use Phoenix.LiveComponent\n  use LiveAssign.LiveComponent\n\n  prop :profile\n  prop :show_avatar?, default: false\n\n  state :age\n  state :expand_details?, default: false\n\n  slot :inner_block\n\n  def handle_event(\"toggle-details\", _, socket) do\n    {:noreply, put_state(socket, expand_details?: not socket.assigns.expand_details?)}\n  end\n\n  @react to: :profile\n  defp put_age(socket) do\n    age = trunc(Date.diff(Date.utc_today(), socket.assigns.profile.birthday) / 365)\n    put_state(socket, age: age)\n  end\n\n  # ...\nend\n```\n\nThe `:profile` assign is a **required prop**. If it is not passed in, a helpful runtime error will occur.\n\nThe `:id` assign is also a required prop, but it is implicitly defined by `use LiveAssign.LiveComponent`, because every LiveComponent requires an `:id`.\n\nThe `:show_avatar?` assign is an **optional prop** that defaults to `false` when unspecified.\n\nThe `:expand_details?` and `:age` assigns are **state**. They can be modified via `put_state/2`.\n\nThe `:inner_block` assign is a **slot prop**. It is required but can be made optional with the `required?: false` option.\n\nThe `put_age/1` function is a **reactive callback**. It is automatically evaluated whenever the value of the `:profiles` state changes. The function can react to prop changes and state changes.\n\n## LiveView Example\n\n```elixir\ndefmodule MyAppWeb.ProfileIndexLive do\n  use Phoenix.LiveView\n  use LiveAssign.LiveView\n\n  state :profiles, default: load_profiles()\n  state :profile_count\n\n  @react to: :profiles\n  defp put_profile_count(socket) do\n    put_state(socket, profile_count: length(socket.assigns.profiles))\n  end\n\n  defp load_profiles, do: # ...\n\n  # ...\nend\n```\n\nThe `:profiles` and `:profile_count` assigns are **state**. They can be modified throughout the LiveView lifecycle, and reactive functions can respond to their changes.\n\nThe `put_profile_count/1` callback is a **reactive function** that is automatically invoked as soon as any changes occur to the `:profiles` state.\n\n## Installation\n\nThe package can be installed by adding `live_assign` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:live_assign, \"~\u003e 0.3.0\"}\n  ]\nend\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschrockwell%2Flive_assign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschrockwell%2Flive_assign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschrockwell%2Flive_assign/lists"}