Patterns for Edit Modal and Page Updates


#1

Hello!

I have a generic modal that renders the form of the section you want to edit.

When you click on the edit button in one of the sections, I want to trigger a modal that will render the form from rails and then inject that into the modal child element.

When the user hits the save button, I want to save the changes in the backend and then return the partial of the updated section.

The problem is it seems like I have to attach the controller to the body or top-level element.
In my example below I have a controller for edit-modal and venture-stage.

The problem is there are multiple sections and it looks like I will end up with a body tag that has multiple controllers. (<body data-controller="edit-modal about venture-stage location highlights"></body>)

Somehow, I feel like there is a better way to do this.

Any thoughts? I included my code below to illustrate what I am trying to accomplish.

It doesn’t look like each controller should know about each other.
the only alternative is for the edit-modal controller to reference the content controllers…
but, then that seems messy as well.

HTML

<body data-controller="edit-modal venture-stage">
  <div class="content">
    <div class="sidebar">
      <div data-target="venture-stage.content">
        <!-- render venture stage data -->
      </div>
      <%= link_to edit_venture_stage_path(@project),
                  remote: true,
                  data: {
                    action: 'ajax:success->edit-modal#onShowForm'
                  } %>
    </div>
    <div class="main">
      <!-- render main content -->
     <div class="modal-wrapper" data-reveal>
       <div target="edit-modal.content">
         <%= form_for venture_stage_path(@project), 
                      remote: true,
                      data: { action: 'ajax:success->edit-modal#onSaveSucess  ajax:success->venture-stage#onUpdate' } do |f| %>
          <!-- rendered form fields -->
        <% end %>
       </div>
     </div>
    </div>
  </div>
</body>

edit_modal_controller.js

import { Controller } from 'stimulus';

export default class extends Controller {
  static targets = [
    'content',
  ]

  connect() {
    this.$modal = $(this.contentTarget.parentNode());
  }

  disconnect() {
    this.$modal.foundation('_destroy');
    this.$modal = null;
  }

  onShowForm(e) {
    const [data, status, xhr] = e.detail;
    this.contentTarger.innerHTML = xhr.response;
    this.show();
  }

  show() {
    this.$modal.foundation('open');
  }

  hide() {
    this.$modal.foundation('close');
  }
}

venture_stage_controller.js

import { Controller } from 'stimulus';

export default class extends Controller {
  static targets = ['content'];

  onUpdate(e) {
    const [data, status, xhr] = e.details;
    this.contentTarget.innerHTML = xhr.response;
  }
}

#2

I suppose I could have one controller for the modal and another for updating the different sections.
Still, it looks like I will need to keep both controllers in the body.

I do feel like this is probably a common pattern for rails CRUD views; any recommendations would be appreciated!

modal view

<div class="modal-wrapper" data-reveal>
  <div target="edit-modal.content">
    <%= form_for venture_stage_path(@project),
                 remote: true,
                 data: {
                   action: 'ajax:success->edit-modal#onSaveSucess  ajax:success->section#onUpdate',
                   section: 'ventureStage'
                 } do |f| %>
      <!-- rendered form fields -->
    <% end %>
  </div>
 </div>

section_controller.js

export default class extends Controller {
  static targets = [
    'ventureStage',
    'location',
    'highlights',
    'oneLiner',
    'desciription',
  ];

  onUpdate(e) {
    const [data, status, xhr] = e.details;
    const currentTarget = `${e.currentTarget.dataset.section}Target`;
    this[currentTarget].innerHTML = xhr.response;
   }
}

#3

After reading through the various forum topics… I realize that I can just use custom events to communicate between the different controllers.