Note: This version has been updated to support both Ecto 1.1 and Ecto 2.0. See Installation for more information.
ExAdmin is an auto administration package for Elixir and the Phoenix Framework, a port/inspiration of ActiveAdmin for Ruby on Rails.
Checkout the Live Demo. The source code can be found at ExAdmin Demo.
Checkout this Additional Live Demo for examples of many-to-many relationships, nested attributes, and authentication.
See the docs and the Wiki for more information.
ExAdmin is an add on for an application using the Phoenix Framework to create a CRUD administration tool with little or no code. By running a few mix tasks to define which Ecto Models you want to administer, you will have something that works with no additional code.
Before using ExAdmin, you will need a Phoenix project and an Ecto model created.
Add ex_admin to your deps:
mix.exs
defp deps do ... {:ex_admin, "~> 0.8"}, ... end
mix.exs
defp deps do ... {:ex_admin, github: "smpallen99/ex_admin"}, ... end
Add some admin configuration and the admin modules to the config file
config/config.exs
config :ex_admin, repo: MyProject.Repo, module: MyProject, # MyProject.Web for phoenix >= 1.3.0-rc modules: [MyProject.ExAdmin.Dashboard, ]
Fetch and compile the dependency
mix do deps.get, deps.compile
Configure ExAdmin:
mix admin.install
Add the admin routes
web/router.ex
defmodule MyProject.Router do use MyProject.Web, :router use ExAdmin.Router ... scope "/", MyProject do... end # setup the ExAdmin routes on /admin scope "/admin", ExAdmin dopipe_through :browseradmin_routes() end
Add the paging configuration
lib/my_project/repo.ex
defmodule MyProject.Repo douse Ecto.Repo, otp_app: :my_projectuse Scrivener, page_size: 10 end
Edit your brunch-config.js file and follow the instructions that the installer appended to this file. This requires you copy 2 blocks and replace the existing blocks.
Start the application with iex -S mix phoenix.server
Visit http://localhost:4000/admin
You should see the default Dashboard page.
To add a model, use admin.gen.resource
mix task:
mix admin.gen.resource MyModel
Add the new module to the config file:
config/config.exs
config :ex_admin, repo: MyProject.Repo, module: MyProject, modules: [MyProject.ExAdmin.Dashboard,MyProject.ExAdmin.MyModel, ]
Start the phoenix server again and browse to http://localhost:4000/admin/my_model
You can now list/add/edit/and delete MyModel
s.
ExAdmin will use your schema's changesets. By default we call the changeset
function on your schema, although you
can configure the changeset we use for update and create seperately.
custom changeset:
defmodule TestExAdmin.ExAdmin.Simple do use ExAdmin.Register register_resource TestExAdmin.Simple doupdate_changeset :changeset_updatecreate_changeset :changeset_create endend
We support many-to-many and has many relationships as provided by Ecto. We recommend using cast_assoc for many-to-many relationships and put_assoc for has-many. You can see example changesets in our test schemas
When passing in results from a form for relationships we do some coercing to make it easier to work with them in your changeset. For collection checkboxes we will pass an array of the selected options ids to your changeset so you can get them and use put_assoc as seen here
In order to support has many deletions you need you to setup a virtual attribute on your schema's. On the related schema you will need to add an _destroy virtual attribute so we can track the destroy property in the form. You will also need to cast this in your changeset. Here is an example changeset. In this scenario a User has many products and products can be deleted. We also have many roles associated.
defmodule TestExAdmin.User do import Ecto.Changeset use Ecto.Schema import Ecto.Query schema "users" dofield :name, :stringfield :email, :stringfield :active, :boolean, default: truehas_many :products, TestExAdmin.Product, on_replace: :deletemany_to_many :roles, TestExAdmin.Role, join_through: TestExAdmin.UserRole, on_replace: :delete end @fields ~w(name active email) def changeset(model, params %{}) domodel|> cast(params, @fields)|> validate_required([:email, :name])|> cast_assoc(:products, required: false)|> add_roles(params) end def add_roles(changeset, params) doif Enum.count(Map.get(params, :roles, [])) > 0 do ids = params[:roles] roles = TestExAdmin.Repo.all(from r in TestExAdmin.Role, where: r.id in ^ids) put_assoc(changeset, :roles, roles)else changesetend endenddefmodule TestExAdmin.Role do use Ecto.Schema import Ecto.Changeset alias TestExAdmin.Repo schema "roles" dofield :name, :stringhas_many :uses_roles, TestExAdmin.UserRolemany_to_many :users, TestExAdmin.User, join_through: TestExAdmin.UserRole end @fields ~w(name) def changeset(model, params %{}) domodel|> cast(params, @fields) endenddefmodule TestExAdmin.Product do use Ecto.Schema import Ecto.Changeset schema "products" dofield :_destroy, :boolean, virtual: truefield :title, :stringfield :price, :decimalbelongs_to :user, TestExAdmin.User end def changeset(schema, params %{}) doschema|> cast(params, ~w(title price user_id))|> validate_required(~w(title price))|> mark_for_deletion end defp mark_for_deletion(changeset) do# If delete was set and it is true, let's change the actionif get_change(changeset, :_destroy) do %{changeset | action: :delete}else changesetend endend
A good blog post exisits on the Platformatec blog describing how these relationships work: http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/
Use the index do
command to define the fields to be displayed.
admin/my_model.ex
defmodule MyProject.ExAdmin.MyModel do use ExAdmin.Register register_resource MyProject.MyModel doindex do selectable_column() column :id column :name actions() # display the default actions columnend endend
The following example shows how to customize the form with the form
macro:
defmodule MyProject.ExAdmin.Contact do use ExAdmin.Register register_resource MyProject.Contact doform contact do inputs doinput contact, :first_nameinput contact, :last_nameinput contact, :emailinput contact, :register_date, type: Date # if you use Ecto :date type in your schemainput contact, :category, collection: MyProject.Category.all end inputs "Groups" doinputs :groups, as: :check_boxes, collection: MyProject.Group.all endend endend
The following example illustrates how to modify the show page.
defmodule MyProject.ExAdmin.Question do use ExAdmin.Register register_resource MyProject.Question domenu priority: 3show question do attributes_table # display the defaults attributes # create a panel to list the question's choices panel "Choices" dotable_for(question.choices) do column :key column :nameend endend endend
Support for custom field types is done in two areas, rendering fields, and input controls.
Use the ExAdmin.Render.to_string/
protocol for rendering types that are not supported by ExAdmin.
For example, to support rendering a tuple, add the following file to your project:
# lib/render.exdefimpl ExAdmin.Render, for: Tuple do def to_string(tuple), do: inspect(tuple)end
Use the :field_type_matching
config item to set the input type.
For example, given the following project:
defmodule ElixirLangMoscow.SpeakerSlug do use EctoAutoslugField.Slug, from: [:name, :company], to: :slugenddefmodule ElixirLangMoscow.Speaker do use ElixirLangMoscow.Web, :model use Arc.Ecto.Model alias ElixirLangMoscow.SpeakerSlug schema "speakers" dofield :slug, SpeakerSlug.Typefield :avatar, ElixirLangMoscow.Avatar.Type endend
Add the following to your project's configuration:
config :ex_admin, # ... field_type_matching: %{ElixirLangMoscow.SpeakerSlug.Type => :string,ElixirLangMoscow.Avatar.Type => :file }
ExAdmin supports 2 themes. The new AdminLte2 theme is enabled by default. The old ActiveAdmin theme is also supported for those that want backward compatibility.
To change the theme to ActiveAdmin, at the following to your config/config.exs
file:
config/config.exs
config :ex_admin, theme: ExAdmin.Theme.ActiveAdmin, ...
The AdminLte2 theme has a number of different skin colors including blue, black, purple, green, red, yellow, blue-light, black-light, purple-light, green-light, red-light, and yellow-light
To change the skin color to, for example, purple:
config/config.exs
config :ex_admin, skin_color: :purple, ...
You can add a theme selector on the top right of the menu bar by adding the following to your config/config.exs
file:
config/config.exs
config :ex_admin, theme_selector: [{"AdminLte", ExAdmin.Theme.AdminLte2},{"ActiveAdmin", ExAdmin.Theme.ActiveAdmin} ], ...
You can override the name of a model by defining a model_name/0
function on
the module. This is useful if you want to use a different module for some of
your actions.
admin/my_model.ex
def model_name do "custom_name"end
ExAdmin leaves the job of authentication to 3rd party packages. For an example of using Coherence checkout the Contact Demo Project.
Visit the Wiki for more information on adding Authentication.
We appreciate any contribution to ExAdmin. Check our CODE_OF_CONDUCT.md and CONTRIBUTING.md guides for more information. We usually keep a list of features and bugs in the issue tracker.
Detailed Example ExAdmin Demo
For a brief tutorial, please visit Elixir Survey Tutorial
Live Demo
Docs
ex_admin
is Copyright (c) 2015-2016 E-MetroTel
The source code is released under the MIT License.
Check LICENSE for more information.