Home > Back-end >  I had a clickable svg that dispatched a stimulus action. I'm trying to recreate the same behavi
I had a clickable svg that dispatched a stimulus action. I'm trying to recreate the same behavi

Time:01-23

I've been working on a demo app in Rails 7.

In one of my views I had the html element 'example-element' which was an image. Clicking the image engaged the link_to tag and directed the user to the example_path. A second element, the svg 'overlay-element' was superimposed over the image. Clicking the svg specifically would dispatch the @example.id to the Stimulus controller overlay#exampleAction. Clicking anywhere else on the image would engage the link_to tag.

<%= link_to example_path(@example), id: 'example-element' do %>
    <%= image_tag @example.image %>
    <svg 
        id="overlay-element"
        data-controller="overlay"
        data-action="click->overlay#exampleAction"
        data-example-id="<%= @example.id %>"
        fill="red" 
        viewBox="0 0 24 24" 
        stroke-width="1.5" 
        stroke="currentColor" 
    >
        <path 
            d="M11..." 
        />
    </svg>
<% end %>

I have updated the code to achieve the same goal with Turbo. I extracted the svg element out into a partial and wrapped it in a turbo_frame_tag and created a new rails controller overlay to receive the post action.

<%= turbo_frame_tag 'layouts/overlay_element' do %>
    <%= button_to overlay_path(example_id: example.id), method: :post do %>
        <svg 
            id="overlay-element"
            fill="red" 
            viewBox="0 0 24 24" 
            stroke-width="1.5" 
            stroke="currentColor" 
        >
            <path 
                d="M11..." 
            />
        </svg>
    <% end %>
<% end %>

I updated the 'example-element' to render the overlay_element partial where I previously had the Stimulus/svg code and pass the @example object in to it.

<%= link_to example_path(@example), id: 'example-element' do %>
    <%= image_tag @example.image %>
    <%= render 'layouts/overlay_element', example: @example %>
<% end %>

It works...sort of... If I remove the link_to tag from the 'example-element' then clicking on the 'overlay-element' posts to the overlay rails controller as expected. If I reinstate the link_to tag to the 'example-element' then clicking anywhere on the 'example-element' OR the 'overlay-element' engages the link_to tag of the 'example-element'. Effectively the 'overlay-element' is now not clickable if the 'example-element' has the link_to tag.

I hoped initially that it might be a z-index issue so I adjusted it to make sure the 'overlay-element' was above the 'example-element' but that didn't work.

Is the problem that I now have a button effectively nested inside a link where before I had a clickable html element nested inside a link? Is it a problem that one is using Turbo and the other is not?

Is there a way of fixing this so that I can click on the 'overlay-element' separately from the 'example-element'?

CodePudding user response:

Could you use a wrapper div to keep the link and button separate and use absolute positioning in CSS to overlap the two? Having a button nested within an a element is invalid in HTML5 (Can I nest a <button> element inside an <a> using HTML5?).

Something like:

<div id="example-element">
  <%= link_to example_path(@example) do %>
    <%= image_tag @example.image %>
  <% end %>
  <%= turbo_frame_tag 'layouts/overlay_element' %>
</div>
  • Related