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 theshow
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!