Lesson 3 Creating a Success Message - BuddyLReno/rails-stimulus-intro GitHub Wiki

⬅️ to Course Overview || 📝 Lesson 3 Feedback || 🐞 Lesson 3 Bug Report

We've got a form connected to our Stimulus controller but the form still uses a regular postback to do it's submission. Let's fix that by hooking into events supplied by Rails-ujs.

✅ Convert form to send via ajax and connect to Stimulus

Relevant docs: Rails-ujs | Rails-ujs event handlers | Actions

Tasks

  • Add remote:true to the form
  • Add the ajax:success action to connect to the stimulus controller
  • Console log to confirm the event was connected correctly

Walkthrough

Converting rails to send forms with ajax is pretty simple. Add remote:true to the form tag. It should look like this.

<%= simple_form_for @short_story, remote: true, data: { action: "keyup->short-story#validateForm" } do |form| %>

That will tell rails the form needs to be submitted using Rails-ujs instead of a simple form postback. During this process, Rails-ujs emits some javascript events that you can listen for and take advantage of. For now, we're going to use ajax:success and connect that to our stimulus controller.

Create a method in your stimulus controller called ajaxSuccess() and modify the data-action property of the form tag to add the new ajax:success action. Multiple actions are separated by a space.

<%= simple_form_for @short_story, 
    remote: true, 
    data: { 
      action: "ajax:success->short-story#ajaxSuccess keyup->short-story#validateForm" 
    } do |form| %>
ajaxSuccess() {
  console.log('Form submitted successfully!');
}

If everything is connected correctly, you should see the "Form submitted successfully!" in your console after submitting the form!

✅ Show a success message after submission

Relevant docs: Targets

The form submits without a postback, but it's kind of useless without showing the user what's happening. Use the new ajaxSuccess method to show the existing Card-successMessage block with a special show class.

Tasks

  • Add a target for successMessage and connect it to stimulus
  • Modify the classlist for the successMessage to add the show class.

Walkthrough

Find the Class-successMessage element and modify it to add the data-target attribute. Add the successMessage to the target list in the stimulus controller.

<p class="Card-successMessage" data-target="short-story.successMessage">
static targets = [
    'submitButton',
    'title',
    'storyText',
    'successMessage'
  ];

Great! Before we move on, let's add a reference to the show class below the previous input variables.

previousTitle = '';
previousStory = '';
showClass = 'show';

Final step is to modify the ajaxSuccess method to add the show class!

ajaxSuccess() {
    this.successMessageTarget.classList.add(this.showClass);
  }

Submitting the form now should show the success message!

✅ Communicate to another controller with custom events

Relevant docs: CustomEvents

💡 If you need to support Internet Explorer, you will need a polyfill for the CustomEvent. The polyfill specifically helps with being able to pass data with the custom event. This polyfill can be found on the MDN link above this message.

Tasks

  • Create a CustomEvent called shortStoryForm:success.
  • Load the CustomEvent with data received from Rails-ujs ajax:success event.
  • Dispatch the event

Walkthrough

You may have noticed a heading below the form called "Last Edit". There's another controller that is tied to an element below that header that will show the last date and time the form was used. The example is a bit contrived, but shows how you can communicate between different controllers with CustomEvents.

Create a method on the stimulus controller called sendSuccessEvent that takes in some data and create a custom event with it, using the name shortStoryForm:success. Then use the document to dispatch the event.

sendSuccessEvent(data) {
    const event = new CustomEvent('shortStoryForm:success', {
      detail: data
    });
    document.dispatchEvent(event);
  }

Any javascript can listen for this event and get the data contained within, specifically the other controller that's also loaded on this page. Let's modify the ajaxSuccess method to accept the event being sent by Rails-ujs. The ajax:success event is a custom event as well with it's data contained in a detail property. Specifically in the first item of the array. Modify the ajaxSuccess method like this:

ajaxSuccess(event) {
    const data = event.detail[0];
    this.sendSuccessEvent(data);
    this.successMessageTarget.classList.add(this.showClass);
  }

Submitting the form now will dispatch this event which will be picked up by the other controller!

If you'd like, you can console log the data to see what the payload looks like. You can also open the short_stories_controller to see how the payload is created with Rails and sent back to the client.

This concludes Lesson 3. On to 🔗 Lesson 4!