{"id":20012299,"url":"https://github.com/archtechx/alpine-reactive","last_synced_at":"2025-10-23T18:06:55.748Z","repository":{"id":57098573,"uuid":"367940820","full_name":"archtechx/alpine-reactive","owner":"archtechx","description":"Reactivity layer for Alpine 2.x","archived":false,"fork":false,"pushed_at":"2021-05-21T18:52:42.000Z","size":12,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-20T04:36:21.515Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/archtechx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-16T17:07:18.000Z","updated_at":"2021-10-14T18:32:08.000Z","dependencies_parsed_at":"2022-08-20T16:51:14.053Z","dependency_job_id":null,"html_url":"https://github.com/archtechx/alpine-reactive","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/archtechx/alpine-reactive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archtechx%2Falpine-reactive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archtechx%2Falpine-reactive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archtechx%2Falpine-reactive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archtechx%2Falpine-reactive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/archtechx","download_url":"https://codeload.github.com/archtechx/alpine-reactive/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archtechx%2Falpine-reactive/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260948803,"owners_count":23087601,"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":[],"created_at":"2024-11-13T07:29:39.831Z","updated_at":"2025-10-23T18:06:50.693Z","avatar_url":"https://github.com/archtechx.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# alpine-reactive\n\nThis package provides a reactivity layer for Alpine 2.x.\n\n## Problem\n\nWhen you create a component that uses a value defined outside of it, you can modify the value from Alpine, but not vice versa:\n\n```html\n\u003cdiv x-data=\"{ counter: window.clickCount }\"\u003e\n    \u003cbutton @click=\"counter++\"\u003e+\u003c/button\u003e\n    Click count: \u003cspan x-text=\"count\" /\u003e\n    \u003cbutton @click=\"counter++\"\u003e--\u003c/button\u003e\n\u003c/div\u003e\n```\n\nClicking the buttons **will** update `window.clickCount`. However when `window.clickCount` is modified outside of the component, Alpine **won't** notice, and won't re-render the DOM.\n\nOnly after something else triggers a re-render, Alpine will show the correct click count again.\n\n## Solution\n\nThis package provides a reactive proxy wrapper for these objects. The syntax is very similar to Vue 3 — you just wrap the variable in `reactive()` and all changes will be tracked.\n\nOne difference between this package's solution and Vue's `reactive()` is that Alpine requires the calls to be **component-specific**. Meaning, the `reactive()` helper also needs the component instance/element. To simplify that, the package also provides a magic Alpine property, `$reactive`.\n\n## Installation\n\n### npm\n\n```sh\nnpm install --save-dev @archtechx/alpine-reactive\n```\n\nThen import the library **before importing Alpine**:\n```js\nimport '@archtechx/alpine-reactive'\n\n// import 'alpinejs'\n```\n\nTo create reactive proxies, import the `reactive` helper:\n\n```js\nimport { reactive } from '@archtechx/alpine-reactive'\n\nwindow.clickCounter = reactive({\n    counter: 10,\n})\n```\n\nThe Alpine hook is executed automatically regardless of what parts of the library you import. For a full reference of the available helpers, see the [Full API](#full-api) section below.\n\n### CDN\n\n```html\n\u003cscript type=\"module\"\u003e\n    import { reactive } from 'https://unpkg.com/@archtechx/alpine-reactive'\n\n    window.clickCounter = reactive({\n        counter: 10,\n    })\n\n    // If you want to use reactive() outside of this script tag:\n    // window.reactive = reactive\n\u003c/script\u003e\n```\n\n## Demo\n\n[View online](https://archtechx.github.io/alpine-reactive/demo.html)\n\n```html\n\u003cscript\u003e\n    window.counter = reactive({\n        count: 10,\n    })\n\u003c/script\u003e\n\n\u003cdiv x-data=\"{ counter: $reactive(window.counter) }\"\u003e\n    \u003cbutton @click=\"counter.count--\"\u003e-\u003c/button\u003e\n    Click count: \u003cspan x-text=\"counter.count\"\u003e\u003c/span\u003e\n    \u003cbutton @click=\"counter.count++\"\u003e+\u003c/button\u003e\n\u003c/div\u003e\n```\n\nUnder the hood, this creates a proxy that forwards everything to `window.clickCount`, but observes changes made to `window.clickCount` and updates the component as needed.\n\nOf course, you may use the same reactive proxy in multiple components.\n\n## Full API\n\n### reactive(target, componentEl = null): Proxy for target\n\nThis creates a reactive proxy for `object`. If `componentEl` is passed, all writes to this proxy will trigger `updateElements()` on `componentEl`'s Alpine instance.\n\n### ref(val): { value: val }\n\nThis turns `foo` into `{ value: foo }`, which allows for `foo` — a primitive type in this example — to be used with proxies.\n\n### isRef(value): bool\n\nChecks if a value is a ref.\n\n### unRef(value)\n\nSyntactic sugar for `isRef(value) ? value.value : value`.\n\n### isReactiveProxy(proxy): bool\n\nChecks whether the passed variable is a value returned by `reactive()`.\n\n### watch(target, (key, value) =\u003e void) or watch(target, value =\u003e void), property)\n\nWatches a reactive proxy, or a property on the reactive proxy.\n\nExample:\n```js\nwatch(window.counter, (key, value) =\u003e console.log(`${key} was changed to ${value}`)); // Watch proxy\nwatch(window.counter, count =\u003e console.log(count), 'count'); // Watch property\n```\n\n## Details\n\nThe package provides a `$reactive` magic property for Alpine. That property is syntactic sugar for `reactive(target, $el)`.\n\n```diff\n- counter: reactive(window.counter, $el)\n+ counter: $reactive(window.counter)\n```\n\nThe magic property is added using the exported `addMagicProperty()` function, which is called once Alpine is available by the `register()` function. `register()` is called automatically for friendly CDN imports.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchtechx%2Falpine-reactive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farchtechx%2Falpine-reactive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchtechx%2Falpine-reactive/lists"}