{"id":16257031,"url":"https://github.com/johnlindquist/rx-handler","last_synced_at":"2025-03-19T22:30:20.292Z","repository":{"id":136551034,"uuid":"132787415","full_name":"johnlindquist/rx-handler","owner":"johnlindquist","description":"A simple function for handling events with streams","archived":false,"fork":false,"pushed_at":"2018-05-10T02:34:45.000Z","size":12,"stargazers_count":67,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-28T21:06:50.296Z","etag":null,"topics":["angular","react","rxjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/johnlindquist.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2018-05-09T16:55:05.000Z","updated_at":"2024-12-20T03:15:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"27465a28-3544-444f-8a13-d2734f879f89","html_url":"https://github.com/johnlindquist/rx-handler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnlindquist%2Frx-handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnlindquist%2Frx-handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnlindquist%2Frx-handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnlindquist%2Frx-handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johnlindquist","download_url":"https://codeload.github.com/johnlindquist/rx-handler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244022639,"owners_count":20385134,"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":["angular","react","rxjs"],"created_at":"2024-10-10T15:47:03.917Z","updated_at":"2025-03-19T22:30:20.279Z","avatar_url":"https://github.com/johnlindquist.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rx-handler\n\n```bash\nnpm i rx-handler\n```\n\n## Hello World\n\n[Hello World Demo](https://stackblitz.com/edit/js-htwrac?file=index.js)\n\n```js\nconst myHandler = handler()\nfrom(myHandler).subscribe(message =\u003e console.log(message)) //logs \"Hello\"\nmyHandler(\"Hello, world!\")\n```\n\n## Handle a Click\n\n[Handle a Click Demo](https://stackblitz.com/edit/typescript-bw3o98?file=index.ts)\n\n```js\nimport { from } from \"rxjs\"\nimport { handler } from \"rx-handler\"\n\nconst button = document.querySelector(\"button\")\n\nconst onClick = handler()\nbutton.addEventListener(\"click\", onClick)\n\nfrom(onClick).subscribe(event =\u003e console.log(event))\n```\n\n## With Operators\n\n[With Operators Demo](https://stackblitz.com/edit/typescript-wxvwhg?file=index.ts)\n\n```js\nimport { from } from \"rxjs\"\nimport { delay, pluck, withLatestFrom } from \"rxjs/operators\"\nimport { handler } from \"rx-handler\"\n\nconst $ = document.querySelector.bind(document)\n\nconst input = $(\"input\")\nconst button = $(\"button\")\n\nconst onInput = handler(pluck(\"target\", \"value\"), delay(250))\ninput.addEventListener(\"input\", onInput)\n\nconst onClick = handler(withLatestFrom(onInput, (click, text) =\u003e text))\nbutton.addEventListener(\"click\", onClick)\n\nfrom(onInput).subscribe(text =\u003e ($(\".output\").innerText = text))\nfrom(onClick).subscribe(event =\u003e console.log(event))\n```\n\n## Angular Hello World\n\n[Angular Hello World Demo](https://stackblitz.com/edit/angular-a8kydb?file=src/app/app.component.ts)\n\n```js\nimport { Component } from \"@angular/core\"\nimport { handler } from \"rx-handler\"\nimport { from } from \"rxjs\"\nimport { map } from \"rxjs/operators\"\n\n@Component({\n  selector: \"my-app\",\n  template: `\u003cdiv\u003e\n  \u003cbutton (click)=\"onClick()\"\u003eClick me\u003c/button\u003e\n  {{date$ | async}}\n  \u003c/div\u003e`\n})\nexport class AppComponent {\n  onClick = handler()\n  date$ = from(this.onClick).pipe(map(() =\u003e Math.random()))\n}\n```\n\n## Angular Multiple Handlers\n\n[Angular Multiple Handlers Demo](https://stackblitz.com/edit/angular-chybye?file=src%2Fapp%2Fapp.component.ts)\n\n```js\nimport { Component } from \"@angular/core\"\nimport { handler } from \"rx-handler\"\nimport { combineLatest, from, merge } from \"rxjs\"\nimport {\n  delay,\n  mapTo,\n  pluck,\n  scan,\n  startWith,\n  withLatestFrom\n} from \"rxjs/operators\"\n\n@Component({\n  selector: \"my-app\",\n  template: `\u003cdiv\u003e\n  \n  \u003cbutton (click)=\"onInc()\"\u003e+\u003c/button\u003e\n  \u003cbutton (click)=\"onDec()\"\u003e-\u003c/button\u003e\n  \u003cdiv\u003e{{count$ | async}}\u003c/div\u003e\n\n  \u003cinput placeholder=\"Type something\" (input)=\"onInput($event)\"/\u003e\n  \u003cdiv\u003e{{text$ | async}}\u003c/div\u003e\n  \n  \u003ch2\u003e{{slicedText$ | async}}\u003c/h2\u003e\n  \u003c/div\u003e`\n})\nexport class AppComponent {\n  onInc = handler(mapTo(1))\n  onDec = handler(mapTo(-1))\n\n  count$ = merge(this.onInc, this.onDec).pipe(\n    startWith(0),\n    scan((count, curr) =\u003e count + curr)\n  )\n\n  onInput = handler(pluck(\"target\", \"value\"), delay(500))\n\n  text$ = from(this.onInput)\n\n  slicedText$ = combineLatest(this.count$, this.text$, (count, text: string) =\u003e\n    text.substring(0, count)\n  )\n}\n```\n\n### Description\n\nInvoking `handler` returns a function that can be observed. Thanks to RxJS v6, `handler` also accepts operators just like `.pipe()`.\n\n```js\nconst myHandler = handler(map(message =\u003e message + \"!\"))\nfrom(myHandler).subscribe(message =\u003e console.log(message)) //logs \"Hello!\"\nmyHandler(\"Hello\")\n```\n\n### Why?\n\nHandlers are a core concept of JavaScript, but were impossible in RxJS until I got this PR accepted: _[Allow Functions in RxJS PR](https://github.com/ReactiveX/rxjs/pull/3562)_\n\nCreating `Subjects` to handle events for Angular templates (or any other frameworks) was a huge pain. It never felt quite right to pass a `Subject` into an event handler and invoke `next` to push values into a stream. I've always wanted to simply \"pass a handler\" to events, but still use streams.\n\n`rx-handler` enables you to pass handlers to events along with the bonus of accepting operators thanks to the new RxJS v6 architecture.\n\n### Special Thanks to [Nicholas Jamieson](https://github.com/cartant)\n\nHe took my idea which used originally used Proxies and [vastly improved it](https://github.com/johnlindquist/react-streams/issues/6#issuecomment-380665956).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnlindquist%2Frx-handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohnlindquist%2Frx-handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnlindquist%2Frx-handler/lists"}