{"id":13807445,"url":"https://github.com/spencer516/ember-functional-modifiers","last_synced_at":"2025-05-14T00:31:31.112Z","repository":{"id":57223828,"uuid":"173442568","full_name":"spencer516/ember-functional-modifiers","owner":"spencer516","description":"Functional Modifiers for Ember","archived":false,"fork":false,"pushed_at":"2019-10-28T18:02:20.000Z","size":1312,"stargazers_count":40,"open_issues_count":0,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-18T23:53:12.971Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spencer516.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-02T12:00:57.000Z","updated_at":"2021-10-24T21:35:20.000Z","dependencies_parsed_at":"2022-08-30T02:40:21.155Z","dependency_job_id":null,"html_url":"https://github.com/spencer516/ember-functional-modifiers","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencer516%2Fember-functional-modifiers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencer516%2Fember-functional-modifiers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencer516%2Fember-functional-modifiers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spencer516%2Fember-functional-modifiers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spencer516","download_url":"https://codeload.github.com/spencer516/ember-functional-modifiers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254046310,"owners_count":22005572,"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-08-04T01:01:25.565Z","updated_at":"2025-05-14T00:31:26.091Z","avatar_url":"https://github.com/spencer516.png","language":"JavaScript","funding_links":[],"categories":["Packages"],"sub_categories":["Modifiers"],"readme":"ember-functional-modifiers\n==============================================================================\n\n\u003e **:warning: :point_right: This addon has been deprecated in favor of the official [`ember-modifier` addon](https://github.com/ember-modifier/ember-modifier). See the [upgrade guide](https://github.com/ember-modifier/ember-modifier#api-differences).**\n\nThis addon provides a [`useLayoutEffect`-like](https://reactjs.org/docs/hooks-reference.html#useeffect) API for adding modifiers to elements in Ember.\n\nFor more information on modifiers, please check out @pzuraq's wonderful [blog post](https://www.pzuraq.com/coming-soon-in-ember-octane-part-4-modifiers/).\n\nCompatibility\n------------------------------------------------------------------------------\n\nThis is currently compatible with:\n\n* Ember.js v2.18 or above\n* Ember CLI v2.13 or above\n\n\nInstallation\n------------------------------------------------------------------------------\n\n```\nember install ember-functional-modifiers\n```\n\nUsage\n------------------------------------------------------------------------------\n\nThis addon does not provide any modifiers out of the box; instead (like Helpers), this library allows you to write your own.\n\n## Generating a Functional Modifier\n\nTo create a modifier (and a corresponding integration test), run:\n\n```\nember g functional-modifier scroll-top\n```\n\n## Example without Cleanup\n\nFor example, if you wanted to implement your own `scrollTop` modifier (similar to [this](https://github.com/emberjs/ember-render-modifiers#example-scrolling-an-element-to-a-position)), you may do something like this:\n\n```js\n// app/modifiers/scroll-top.js\nimport makeFunctionalModifier from 'ember-functional-modifiers';\n\nexport default makeFunctionalModifier((element, [scrollPosition]) =\u003e {\n  element.scrollTop = scrollPosition;\n})\n```\n\nThen, use it in your template:\n\n```hbs\n\u003cdiv class=\"scroll-container\" {{scroll-top @scrollPosition}}\u003e\n  {{yield}}\n\u003c/div\u003e\n```\n\n## Example with Cleanup\n\nIf the functionality you add in the modifier needs to be torn down when the element is removed, you can return a function for the teardown method.\n\nFor example, if you wanted to have your elements dance randomly on the page using `setInterval`, but you wanted to make sure that was canceled when the element was removed, you could do:\n\n```js\n// app/modifiers/move-randomly.js\nimport makeFunctionalModifier from 'ember-functional-modifiers';\n\nconst { random, round } = Math;\n\nexport default makeFunctionalModifier(element =\u003e {\n  const id = setInterval(() =\u003e {\n    const top = round(random() * 500);\n    const left = round(random() * 500);\n    element.style.transform = `translate(${left}px, ${top}px)`;\n  }, 1000);\n\n  return () =\u003e clearInterval(id);\n});\n\n```\n\n```hbs\n\u003cbutton {{move-randomly}}\u003e\n  {{yield}}\n\u003c/button\u003e\n```\n\n## Example with Cleanup (on destroy)\n\nBy default, a functional modifier that returns a cleanup method will trigger the cleanup on each change — the reason for this is similar to the reason for the same behavior with [`useEffect`](https://reactjs.org/docs/hooks-effect.html#explanation-why-effects-run-on-each-update) in React.\n\nIf, however, unsubscribing/resubscribing on every change is a particularly expensive action, you may only want to cleanup when the element is about to be removed, not when it updates. (An aside: Because you have to track some state between modifier calls, a better solution _may_ be to use [`ember-oo-modifiers`](https://github.com/sukima/ember-oo-modifiers) instead).\n\nBut you can do it with a functional modifier. For example, let's imagine that we're using an RxJS observable-like thing that lets us hot-swap the action it fires. That may look something like:\n\n```js\n// app/modifiers/my-rx-thing.js\nimport makeFunctionalModifier from 'ember-functional-modifiers';\nimport subscribe from './my-rx-js-observer';\n\nconst OBSERVERS = new WeakMap();\n\nexport default makeFunctionalModifier((element, [action]) =\u003e {\n  const observer = OBSERVERS.has(element) ? OBSERVERS.get(element) : subscribe(element);\n\n  observer.updateAction(action);\n\n  OBSERVERS.set(element, observer);\n\n  return (isRemoving) =\u003e {\n    if (isRemoving) {\n      observer.unsubscribe();\n    }\n  };\n});\n```\n\n```hbs\n\u003cbutton {{my-rx-thing (action \"handleAction\")}}\u003e\n  Click Me!\n\u003c/button\u003e\n```\n\n## Example with Service Injection\n\nYou may also want to inject a service into your modifier.\n\nYou can do that by supplying an injection object before the the modifier function. For example, suppose you wanted to track click events with `ember-metrics`:\n\n```js\n// app/modifiers/track-click.js\nimport makeFunctionalModifier from 'ember-functional-modifiers';\n\nfunction trackClick(metrics, element, [eventName], options) {\n  const callback = () =\u003e metrics.trackEvent(eventName, options);\n\n  element.addEventListener('click', callback, true);\n\n  return () =\u003e element.removeEventListener('click', callback);\n}\n\nexport default makeFunctionalModifier(\n  { services: ['metrics'] },\n  trackClick\n);\n```\n\nThen, you could use this in your template:\n\n```hbs\n\u003cbutton {{track-click \"Clicked the THING!\"}}\u003e\n  Click Me!\n\u003c/button\u003e\n```\n\n*NOTE*: Because we are not observing the properties in the service in any way, if we are _reading_ a property on a service, the modifier will not recompute if that value changes. If that's the behavior you need, you probably want to pass that value into the modifier as an argument, rather than injecting it.\n\nContributing\n------------------------------------------------------------------------------\n\nSee the [Contributing](CONTRIBUTING.md) guide for details.\n\nReleasing\n------------------------------------------------------------------------------\n\n```sh\nyarn release\n```\n\n\nLicense\n------------------------------------------------------------------------------\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspencer516%2Fember-functional-modifiers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspencer516%2Fember-functional-modifiers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspencer516%2Fember-functional-modifiers/lists"}