Stimulus async load Rails HTML - `Rails.ajax` the `render_to_string` way (full)
Today I've Learned postor: How to load Rails HTML content with Stimulus JS with Rails.ajax
without using RJS
This is subarticle of Stimulus JS Cheat Sheet
I also wrote Rails.ajax
the RJS (format.js
) way (so exact oposit of this solution)
Rails stuff
# config/routes.rb
# ...
resources :entries_search, only: [] do
post :load_sub_category, on: :collection
end
# ...
# /app/controllers/entries_search_controller.rb
class EntriesSearchController < ApplicationController
def load_sub_category
main_category = Category.find(params[:main_category_id])
render json: { html: render_to_string(partial: 'entries_search/categories', locals: { main_category: main_category}) }
end
end
-# /app/views/entries_search/index.html.slim
div data-controller="entries-search" data-entries-search-categories-load-path="#{load_sub_categories_entries_search_index_path}"
div data-target="entries-search.categories"
.chip.hoverable data-action="click->entries-search#loadSubCategories" data-main-category-id="123"
| Load "Puppies" Sub Categories
.chip.hoverable data-action="click->entries-search#loadSubCategories" data-main-category-id="345"
| Load "Kittens" Sub Categories
note:
load_sub_categories_entries_search_index_path
is being translated to/entries_search/load_sub_categories
by Rails routes
-# /app/views/entries_search/_categories.html.slim
- main_category.sub_categories.each do |sub_category|
.chip= sub_category.title
JS stuff
//package.json
{
"dependencies": {
# ...
"@rails/ujs": "^6.0.0-alpha",
"stimulus": "^1.1.1",
# ...
}
}
// app/javascript/controllers/entries_search_controller.js
import { Controller } from "stimulus"
import Rails from "@rails/ujs";
export default class extends Controller {
static targets = [ "categories" ]
loadSubCategories(e) {
let categoriesLoadPath = this.data.get('categories-load-path');
let mainCategoryId = e.currentTarget.dataset.mainCategoryId;
let categoriesTargetDiv = this.categoriesTarget;
Rails.ajax({
type: "post",
dataType: 'json',
url: categoriesLoadPath,
data: `main_category_id=${mainCategoryId}`,
success: function(data) { categoriesTargetDiv.innerHTML = data.html; },
error: function(data) { alert('Error: no Category match this ID') }
})
}
}
note: Yes you can just use fetch like shown in this article. I just like use
Rails.ajax
as show in this article.
Other sources
Entire blog website and all the articles can be forked from this Github Repo