# Custom Controls

Define exactly what actions users can take based on their role or context. Prevent costly mistakes while empowering users.

- Price: $20/month
- Gem: `gem "avo-custom_controls"`
- Web page: https://avohq.io/addons/custom-controls
- Pricing: https://avohq.io/pricing.md

The row of buttons at the top of every record, Edit, Delete, Save, Back, is the part of Avo your team clicks all day. By default Avo decides what sits there. With Custom Controls, you make that call: define `show_controls`, `edit_controls`, `index_controls`, or `row_controls` on a resource and build each bar from the pieces you want, in the order you want, across your [Show](https://docs.avohq.io/4.0/views.html#Show), [Edit](https://docs.avohq.io/4.0/views.html#Edit), [Index](https://docs.avohq.io/4.0/views.html#Index), and table-row views.

Compose the built-in buttons (`back_button`, `edit_button`, `delete_button`, `save_button`) with your own `link_to` links, Avo actions, and dropdown groups, set each one's label, icon, style, and color, and wrap any of them in plain Ruby conditionals so a control only shows when the record calls for it. It's a few methods your agent writes on a control layer that's already built, and it keeps working with every Avo release.

## See it in action

![Show controls bar](https://avohq.io/assets/addons/custom-controls/show-controls-7b600a8c86c7a1eaa7ef88fc710462ecc1274c466df7b03e0b2b299be974755c.png)

 Show controls

![Edit controls bar](https://avohq.io/assets/addons/custom-controls/edit-controls-683eb16969e0f1e02ca66da9d30875c7202d2b9dfec0ed2e18b9549aeae85ca4.png)

 Edit controls

![Index controls bar](https://avohq.io/assets/addons/custom-controls/index-controls-8cd8c20e505dafe64c328d1b74951e45139e5122f616602af964edb5902c0372.png)

 Index controls

![Row controls bar](https://avohq.io/assets/addons/custom-controls/row-controls-8124835ababae3ed6825ae6f18a370e2168158e4b63fde5624215625f5ba127b.png)

 Row controls

## What it looks like

Each bar is a block on the resource. Compose built-in buttons, your own links, and Avo actions, and reach for [`default_controls`](https://docs.avohq.io/4.0/customizable-controls.html#default-controls) when you only want to add to Avo's defaults rather than replace them.

Docs for each bar: [Show](https://docs.avohq.io/4.0/customizable-controls.html#Show%20page), [Edit](https://docs.avohq.io/4.0/customizable-controls.html#Edit%20page), [Index](https://docs.avohq.io/4.0/customizable-controls.html#Index%20page), and [Row](https://docs.avohq.io/4.0/customizable-controls.html#Row%20controls).

```
# app/avo/resources/post.rb
class Avo::Resources::Post < Avo::BaseResource
  # Show: built-ins plus a custom link and an action, shown conditionally
  self.show_controls = -> do
    back_button label: ""
    link_to "View on site", post_path(record), target: :_blank
    action Avo::Actions::Publish, style: :primary unless record.published?
    delete_button
    edit_button
  end

  # Edit: keep Avo's defaults, add one button of your own
  self.edit_controls = -> do
    link_to "Preview", preview_post_path(record), target: :_blank
    default_controls
  end

  # Index: group links into a dropdown, then the create button
  self.index_controls = -> do
    list label: "Export", icon: "heroicons/outline/arrow-down-tray" do
      link_to "CSV", export_posts_path(format: :csv)
      action Avo::Actions::EmailReport
    end
    create_button label: "New post"
  end

  # Row: per-record buttons, hidden in grid view
  self.row_controls = -> do
    action Avo::Actions::Feature, label: "Feature", style: :primary unless params[:view_type] == "grid"
    show_button
    edit_button
    delete_button
  end
end
```

## What you get

- Separate control bars for Show, Edit, Index, and table-row views via `show_controls`, `edit_controls`, `index_controls`, and `row_controls`
- Built-in buttons to compose: `back_button`, `edit_button`, `delete_button`, `save_button`, `create_button`, `detach_button`, and `attach_button`
- Add your own `link_to` links, trigger Avo actions, and group items into dropdown lists with dividers
- Per-control label, title, icon (Heroicons), style (`:primary`, `:outline`, `:text`), and color
- Plain Ruby conditionals to show or hide a control based on the record
- `default_controls` to drop Avo's standard buttons back in alongside your custom ones

## Why it pays off

- Rearranging a control bar with a custom button takes a few lines in the resource this afternoon, not a custom view layer you spec and build over a sprint.
- Every Avo release makes it better: the control bars on Show, Edit, Index, and row views keep working through upgrades, with no overridden templates to re-patch.
- The DSL covers Show, Edit, Index, and row contexts across many apps, so it handles authorization and per-view differences a one-off override tends to skip.
- Your agent configures the same control DSL in every app, instead of generating a different override each time.

Included in bundles: Essentials ($75/month)
