{"id":18982345,"url":"https://github.com/defactosoftware/ex_cell","last_synced_at":"2025-04-15T18:03:26.266Z","repository":{"id":23249622,"uuid":"98533481","full_name":"DefactoSoftware/ex_cell","owner":"DefactoSoftware","description":"A module for creating coupled modules of CSS, Javascript and Views in Phoenix","archived":false,"fork":false,"pushed_at":"2024-11-15T12:28:19.000Z","size":149,"stargazers_count":29,"open_issues_count":10,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-15T18:02:59.844Z","etag":null,"topics":["components","elixir","elixir-phoenix","frontend"],"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/DefactoSoftware.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}},"created_at":"2017-07-27T12:31:09.000Z","updated_at":"2024-11-15T12:28:22.000Z","dependencies_parsed_at":"2024-11-08T16:13:14.742Z","dependency_job_id":"d6927f0a-ab2b-4483-8d06-8499e7d3641a","html_url":"https://github.com/DefactoSoftware/ex_cell","commit_stats":{"total_commits":104,"total_committers":9,"mean_commits":"11.555555555555555","dds":0.6730769230769231,"last_synced_commit":"9532a596fabf723449c55861d249ca9fc6984f90"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Fex_cell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Fex_cell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Fex_cell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Fex_cell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DefactoSoftware","download_url":"https://codeload.github.com/DefactoSoftware/ex_cell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249125958,"owners_count":21216705,"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":["components","elixir","elixir-phoenix","frontend"],"created_at":"2024-11-08T16:13:10.917Z","updated_at":"2025-04-15T18:03:26.249Z","avatar_url":"https://github.com/DefactoSoftware.png","language":"Elixir","readme":"[![Hex.pm](https://img.shields.io/hexpm/v/ex_cell.svg)](https://hex.pm/packages/ex_cell)\n[![CircleCI](https://circleci.com/gh/DefactoSoftware/ex_cell/tree/master.svg?style=shield)](https://circleci.com/gh/DefactoSoftware/ex_cell)\n\n# ex_cell\n\nA module for creating coupled modules of CSS, Javascript and Views in Phoenix.\n\n## Installation\n\nAdd the following to the dependencies in `mix.exs`:\n\n```ex\n{:ex_cell, \"~\u003e 0.0.14\"}\n```\n\nIn Phoenix 1.3.0+ add the following to `lib/app_web/web.ex`:\n\n```ex\ndef controller do\n  quote do\n  ...\n\n  import ExCell.Controller\n\n  ...\n  end\nend\n\ndef view(opts \\\\ []) do\n  quote do\n    ...\n\n    import ExCell.View\n\n    ...\n  end\nend\n\ndef cell(opts \\\\ []) do\n  quote do\n    use ExCell.Cell, namespace: AppWeb,\n                     adapter: ExCell.Adapters.CellJS\n\n    use Phoenix.View, root: \"lib/app_web/cells\",\n                      path: ExCell.View.relative_path(__MODULE__, AppWeb)\n\n    import Phoenix.Controller,\n           only: [get_csrf_token: 0, get_flash: 2, view_module: 1]\n\n    use Phoenix.HTML\n\n    import AppWeb.Router.Helpers\n    import AppWeb.Gettext\n\n    # Add everything you want to use in the cells\n  end\nend\n```\n\nNow you can add a cells/ directory in lib/app_web and place cells in that\ndirectory.\n\nEvery cell should contain a view.ex and a template.html.eex. The view and\ntemplate are tightly linked together by the Cell.\n\n## CSS\n\nTo ensure all the CSS can be placed next to your cell you need to add the\nfollowing to your `brunch-config.js`:\n\n```js\n...\nstylesheets: {\n  joinTo: {\n    \"css/app.css\": [\n      \"assets/css/app.css\",\n      \"lib/app_web/cells/**/*.css\"\n    ]\n  }\n}\n...\n```\n\nIf you use something other than [Brunch](https://brunch.io) to manage your assets,\nyou need to add the files to the assets manager of choice.\n\n## Javascript\n\nIf you wish to use the accompanying [cell-js](https://github.com/DefactoSoftware/cell-js)\nlibrary you can install it with your package manager. After you installed the\nJavascript package, add the following to your `brunch-config.js`:\n\n```js\n...\njavascripts: {\n  joinTo: {\n    \"js/vendor.js\": /^node_modules/,\n    \"js/app.js\": [\n      \"assets/js/**/*.js\",\n      \"lib/app_web/cells/**/*.js\"\n    ]\n  }\n}\n...\n```\n\n## Usage\n\nA cell consists of a couple of files:\n\n```\ncells\n|- avatar\n|  |- template.html.eex\n|  |- view.ex\n|  |- style.css (optional)\n|  |- index.js (optional)\n|- header\n...\n```\n\nYou can render the cell in a view, controller or another cell by adding the\nfollowing code:\n\n```ex\ncell(AvatarCell, class: \"CustomClassName\", user: %User{})\n```\n\nThis would generate the following HTML when you render the cell:\n\n```html\n\u003cspan class=\"AvatarCell\" data-cell=\"AvatarCell\" data-cell-params=\"{}\"\u003e\n  \u003cimg src=\"/images/foo/avatar.jpg\" class=\"AvatarCell-Image\" alt=\"foo\" /\u003e\n\u003c/span\u003e\n```\n\n### view.ex\n\nViews of cells behave like normal views in Phoenix, except that they have\nprovide a container method that can be used in a template to render the\nappropriate HTML needed to initialize the Javascript for a cell and have a\npredefined class that is the same as the cell name minus the namespace.\n\n```ex\n# lib/app_web/cell/avatar/view.ex\ndefmodule AppWeb.AvatarCell do\n  @moduledoc \"\"\"\n  The avatar cell used to render the user avatars.\n  \"\"\"\n\n  use AppWeb, :cell\n  alias App.Accounts.Avatar\n\n  def class_names(assigns) do\n    [assigns[:class], class_name(assigns[:size])]\n    |\u003e Enum.reject(fn(v) -\u003e is_nil(v) end)\n  end\n\n  def avatar_image_path(user) do\n    Avatar.url({user.avatar, user}, :thumb)\n  end\n\n  def avatar_image_alt(user) do\n    [user.first_name, user.last_name]\n    |\u003e Enum.join(\" \")\n    |\u003e String.trim()\n  end\nend\n```\n\n### template.html.eex\n\nThe template behave like any other template in Phoenix except that they have\naccess to a container method to render the appropriate cell HTML container:\n\n```eex\n\u003c!-- lib/app_web/cell/avatar/template.html.eex --\u003e\n\u003c%= container(tag: :span,  class: class_names(assigns)) do %\u003e\n  \u003c%= if image_path = avatar_image_path(@user) do %\u003e\n    \u003c%= img_tag(image_path, class: class_name(\"image\"), alt: avatar_image_alt(@user)) %\u003e\n  \u003c% end %\u003e\n\u003c% end %\u003e\n```\n\n### style.css\n\nThis can be any type of CSS file that you wish (preprocessed or other wise).\nBecause cells provides methods to namespace your CSS you are advised to use a\nsimilar namespace or use something like [postcss-modules](https://github.com/css-modules/postcss-modules)\nto ensure all classes defined are unique.\n\n```css\n/* lib/app_web/cell/avatar/style.css */\n.AvatarCell {\n  border-radius: 50%;\n  height: 50px;\n  width: 50px;\n}\n\n.AvatarCell-image {\n  display: inline-block;\n  max-width: 100%;\n}\n```\n\n### index.js\n\nIf you use [cell-js](https://github.com/DefactoSoftware/cell-js) you can create\nJavascript that is tightly coupled to the cell:\n\n```js\n// lib/app_web/cells/avatar/index.js\nimport { Cell, Builder } from \"@defacto/cell-js\";\n\nclass AvatarCell extends Cell {\n  initialize() {\n    this.element.addEventListener(\"click\", this.onToggleOpenClass);\n  }\n\n  onToggleOpenClass = e =\u003e this.element.classList.toggle(\"open\");\n}\n\nBuilder.register(AvatarCell, \"AvatarCell\");\n\nexport default AvatarCell;\n```\n\n## Nested cells\n\nFor nested cells (e.g. `AppWeb.User.AvatarCell`) make sure you include the\nnamespace in the stylesheet/javascript.\n\n```css\n.User-AvatarCell {}\n```\n\n```js\nBuilder.register(AvatarCell, \"User-AvatarCell\");\n```\n\nWhen in doubt, the cell name corresponds to the `data-cell` attribute on the DOM element.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefactosoftware%2Fex_cell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefactosoftware%2Fex_cell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefactosoftware%2Fex_cell/lists"}