Open a popover from another one
This example requires the Stimulus controller setup shown in Use Stimulus and Turbo example.
<%# app/views/projects/index.html.erb %>
<table class="table">
<thead>
<th class="w-1/4">Name</th>
<th class="w-1/4">Manager</th>
<th class="w-1/4">Actions</th>
</thead>
<tbody>
<% @projects.each do |project| %>
<tr>
<td>
<%= link_to project.name, project_path(project) %>
</td>
<td>
<%= link_to project.manager, manager_path(project.manager), class: "link" %>
</td>
<td>
<%#
this 'inline-block' and 'block' combination is required for the comment
popover to match the width and placement of the actions popover.
%>
<div class="inline-block">
<%= coupdoeil_popover_tag ProjectPopover.with(project:).actions,
nil, # popover options
class: "inline-block" do %>
<button type="button" class="btn">actions</button>
<% end %>
<%# this coup-doeil has no content since it's triggered manually %>
<%= coupdoeil_popover_tag ProjectPopover.with(project:).comment,
nil, # popover options
class: "block",
id: dom_id(project, :comment_popover)
%>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
# app/popovers/project_popover.rb
class ProjectPopover < ApplicationPopover
before_action :set_project
default_options_for :actions, animation: false
default_options_for :comment, animation: "fade-in"
default_options_for :actions, :comment,
placement: "bottom-end, top-end",
offset: "0.25rem",
trigger: :click
def actions
end
def comment
end
private
def set_project
@project = params[:project]
end
end
Note that comment popover must have trigger option set to click so it doesn’t close when mouse is hovering over any other element.
<%# app/popovers/project_popover/actions.html.erb %>
<ul class="menu bg-base-200 rounded-box w-56">
<li>
<%= button_tag "Comment",
type: :button,
data: {
action: "click->popover#openOtherPopover", # see stimulus controller below
popover_target_param: dom_id(@project, :comment_popover)
}
%>
</li>
<%= coupdoeil_popover_tag ProjectPopover.with(project: @project).export_actions do %>
<%# … %>
<% end %>
</ul>
<%# app/popovers/project_popover/comment.html.erb %>
<div class="bg-white p-2 rounded border border-gray-300 shadow">
<%= form_for @project,
html: { data: { action: "turbo:submit-end->popover#closeOnSubmitSuccess" } } do |f| %>
<%= f.textarea :comment, class: "border-gray-300 rounded text-sm p-1" %>
<%= f.submit "comment", class: "block w-full btn btn-xs btn-success" %>
<% end %>
</div>
// app/javascript/controllers/popover_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="popover"
export default class extends Controller {
// check "Use Stimulus and Turbo" example page for rest of controller
openOtherPopover(event) {
const { target: coupdoeilId } = event.params
const coupdoeil = document.getElementById(coupdoeilId)
// it's always nice to help yourself understand your mistakes
if (!coupdoeil) {
throw new Error("No element was found with this id.")
} else if (coupdoeil.tagName !== "COUP-DOEIL") {
throw new Error("Element was found but it is not a coup-doeil.")
}
this.close() // close current popover
coupdoeil.openPopover()
}
closeOnSubmitSuccess(event) {
if (event.detail.success) {
this.close()
} else {
// handle error if needed
}
}
}
The rest of the Stimulus controller can be seen in Use Stimulus and Turbo example. The full file can also be found in the repository: app/javascript/controllers/popover_controller.js
.