import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="form"
export default class extends Controller {
static targets = [ "error" ]
static values = { target: String, action: String }
connect() {
this.target = this.hasTargetValue && document.querySelector(this.targetValue);
this.action = this.hasActionValue && this.actionValue;
this.actions = ["beforebegin", "afterbegin", "beforeend", "afterend"];
console.log(this);
}
handleRequest(event){
const { status, response } = event.detail[0];
if(status >= 200 && status <= 299) {
this.handleSuccess(response);
}
if(status >= 400) {
this.handleError(response);
}
}
handleError(response){
this.errorTarget.innerHTML = response;
}
handleSuccess(response) {
this.clearErrors();
this.clearForm();
if(this.actionIsPermitted(this.action)) {
this.target.insertAdjacentHTML(this.action, response);
} else {
this.target.innerHTML = response;
}
}
clearErrors(){
this.hasErrorTarget && (this.errorTarget.innerHTML = "");
}
clearForm(){
this.element.reset();
}
actionIsPermitted(action) {
if(this.actions.indexOf(action) == -1) {
return false;
} else {
return true;
}
}
}
class TasksController < ApplicationController
def create
@task = Task.new(task_params)
if @task.save
render @task, layout: false
else
render(
partial: "layouts/form_errors",
locals: { object: @task },
status: :unprocessable_entity,
layout: false
)
end
end
end
<%= render partial: "form" %>
<ul id="tasks">
<%= render @tasks %>
</ul>
<%= form_with(
model: @task,
local: false,
data: {
controller: "form",
form_target_value: "#tasks",
form_action_value: "afterbegin",
action: "ajax:complete->form#handleRequest"
}
) do |form| %>
<div data-form-target="error">
<%= render partial: "layouts/form_errors", locals: { object: form.object } %>
</div>
<%= form.text_field :title %>
<%= form.submit %>
<% end %>