Data target in partials

I’m using Stimulus ina Rails (5.2) app and I have created a controller to manage Tags (A Project have many Tags).
Within the controller, I currently display the form used to add a Tag,

<div class='' data-controller='tags'>
    <div class='tags'>
      <%= render @project.tags %>
      <div class='' data-action='click->tags#displayForm' data-target='tags.addButton'>add tag</div>
    </div>

    <%= form_with model: Tag.new, url: project_tags_path(@event) do |f|  %>
      <div class='' data-target='tags.form'>
        <%= f.text_field :name, class: '', data: { action: 'keyup->tags#toggleSubmitButton', target: 'tags.textField' } %>
        <%= button_tag 'add tag', type: 'submit', class: '', data: { target: 'tags.submitButton' } %>
        <%= tag.a 'dismiss', class: '', data: { action: 'click->tags#hideForm', target: 'tags.dismissButton' } %>
    </div>
  <% end %>
</div>


import { Controller } from "stimulus"

export default class extends Controller {
  static targets = ["form", "addButton", "submitButton", "textField"]

  connect() {
   ...
  }

  displayForm() {
   ...
  }

  hideForm() {
   ...
  }

  toggleSubmitButton() {
  ...
  }
}

Now I’d like to add the ability to delete a tag by clicking on a button inside the tag.

#_tag.html.erb
<div class=''>
  <%= tag.name %>
  <button class=''></button>
</div>

My first idea was to add this functionality to the TagsController as follows

<div class=''>
  <%= tag.name %>
  <button class='' data-action='click->tags#deleteTag' data-target='tags.deleteButton'></button>
</div>

However, this works only for the first Tag.

So, what is the preferred way to deal with repeated elements (partials)?
Should I have a controller dedicated to deleting the Tag like below

<div class='' data-controller="deleteTags">
  <%= tag.name %>
  <button class='' data-action='click->deleteTags#deleteTag' data-target='deleteTags.deleteButton'></button>
</div>

Having already all the logic related to the creation in the TagController it makes sense to me to keep also the one responsible for deleting Tags in same controller.

Show us your tags#deleteTag handler.

If it removes the tag clicked on by targeting the parent of the event.target element - it should work for all tags without any data-target on the them.

Hi @stevenchanin,
I’m very new to Stimulus so I probably do if the wrong way.

Compared to the code above, I have added to the button an extra data attribute, data-url, which contain the action to call.

<button class='' data-action='click->tags#deleteTag' data-target='tags.deleteButton' data-URL=<%= projects_tag_path(@project, tag) %>></button>

Now in deleteTag I just need to be able to access the data-URL of the button I click (the ajax call is not an issue). So I have

        deleteTag() { console.log(this.deleteButtonTarget.getAttribute('data-url'))
        } 

Thanks

you need to use the event that is passed to the delete function

deleteTag(event) { 
  console.log(event.target.getAttribute('data-url'))
} 

You can read more details here : https://stimulusjs.org/reference/actions especially regarding the difference between event.target and event.currentTarget

1 Like

@adrienpoly Thanks for the reply.

@adrienpoly response is right, I just want to add that you can get the data attributes using the ES API:

console.log(event.target.dataset.url)

Examples

1 Like