'Rails 7 vanilla-nested gem link to add item not working
I am trying to use the vanilla-nested gem, with Rails 7, to add an item in a nested edit form. The link is not work and not action results.
I have tried to follow the example code in the gem test path for rails 7.
Here is the edit view:
activities/edit.html.erb
<div class="container">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<br>
<h1 class="m-0 text-dark">Update Transaction</h1>
</div>
</div>
</div>
</div>
<%= render "form", activity: @activity %>
The form partial:
activities/_form.html.erb
<div class="row no-gutters">
<div class="col-auto">
<%= image_tag '16419114852474091540459891939039.jpeg', class: "main-image",
width: "658", sizes: "(max-width: 767px) 96vw, (max-width: 991px) 354px, 460px", alt: ""
%>
</div>
<div class="col">
<div class="card-block px-2">
<%= form_for activity do |form| %>
<div class="row">
<%= form.label :date_submitted, class: 'col-lg-3 text-right', style: "display: block" %>
<div class="col-lg-2">
<%= form.date_field :date_submitted %>
</div>
</div>
<br>
<div class="row">
<%= form.label :transaction_date, class: 'control-label col-lg-3', style: "display: block" %>
<div class="col-lg-2">
<%= form.date_field :activity_date %>
</div>
</div>
<br>
<div>
<div class="row">
<div class="col-lg-8">
<h3>Transaction Items</h3>
<%= link_to_add_nested(form, :items, '#items') do %>
<span><span> Add Item</span></span>
<% end %>
</div>
</div>
<div id='items'>
<%= form.fields_for :items do |sub_form| %>
<%= render 'item_fields', form: sub_form %>
<% end %>
</div>
</div>
<div>
<%= form.submit 'Save Update', class: "btn btn-primary" %>
</div>
<% end %>
<br>
</div>
</div>
</div>
<div class="card-footer w-100 text-muted">
<div>
<%= link_to "Show this activity", @activity %> |
<%= link_to "Back to activities", activities_path %>
</div>
</div>
The fields partial:
activities/_item_fields.html.erb
<div class="item-fields">
<div class="row">
<div class="col-lg-6">
<%= form.label :amount, style: "display: block" %>
<%= form.text_field :item_amount %>
</div>
<div class="col-lg-4">
<%= form.label :vendor, style: "display: block" %>
<%= form.text_field :vendor %>
</div>
</div>
<br>
<div class="row">
<div class="col-lg-6">
<%= form.label :expense_category, style: "display: block" %>
<%= form.select(:expense_category, @category_choices) %>
</div>
<div class="col-lg-4">
<%= form.label :transaction_type, style: "display: block" %>
<%= form.select(:transaction_type, @transaction_choices) %>
</div>
</div>
<br>
</div>
The Items model
models/item.rb
class Item < ApplicationRecord
belongs_to :activity
end
The Activity model:
models/activity.rb
class Activity < ApplicationRecord
belongs_to :account
belongs_to :user
has_many :items, dependent: :destroy
accepts_nested_attributes_for :items, reject_if: :all_blank
has_one_attached :activity_image
validate :acceptable_image
def acceptable_image
return unless activity_image.attached?
unless activity_image.byte_size <= 5.megabyte
errors.add(:activity_image, "is too big")
end
acceptable_types = ["image/jpeg", "image/png"]
unless acceptable_types.include?(activity_image.content_type)
errors.add(:activity_image, "must be a JPEG or PNG")
end
end
end
The Activities controller
controllers/activities_controller.rb
class ActivitiesController < ApplicationController
before_action :set_activity, only: %i[ show edit update destroy add_item ]
# GET /activities or /activities.json
def index
@activities = Activity.all
end
# GET /activities/1 or /activities/1.json
def show
end
# GET /activities/new
def new
@activity = Activity.new
@activity.items.build
end
# GET /activities/1/edit
def edit
set_transaction_choices
set_category_choices
end
# POST /activities or /activities.json
def create
@activity = Activity.new(activity_params)
respond_to do |format|
if @activity.save
format.html { redirect_to activity_url(@activity), notice: "Activity was successfully created." }
format.json { render :show, status: :created, location: @activity }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @activity.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /activities/1 or /activities/1.json
def update
respond_to do |format|
if @activity.update(activity_params)
format.html { redirect_to activity_url(@activity), notice: "Activity was successfully updated." }
format.json { render :show, status: :ok, location: @activity }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @activity.errors, status: :unprocessable_entity }
end
end
end
# DELETE /activities/1 or /activities/1.json
def destroy
@activity.destroy
respond_to do |format|
format.html { redirect_to activities_url, notice: "Activity was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_activity
@activity = Activity.find(params[:id])
end
# Only allow a list of trusted parameters through.
def activity_params
params.require(:activity).permit(:account_id, :user_id, :date_submitted,
:activity_date, :reviewed, :finalized, :notes, :emailed_question,
items_attributes: [ :id, :item_amount, :vendor,
:expense_category, :transaction_type])
end
def set_transaction_choices
@transaction_choices = [["Expense", 'expense'], ["Revenue", 'revenue']]
end
def set_category_choices
@category_choices = ['Fuel', 'Tolls',
'Repairs and Maintance', 'Plates', 'Truck Insurance',
'Cell Phone', 'Internet', 'Satellite', 'Perdiem Days',
'Office Supplies', 'Professional Services',
'Other expenses', 'Liability Insurnace', 'Health Insurnace',
'Truck Supplies and Equipment',
'Working Clothes and Gear', 'Lease and Rental Fees',
'Taxes and Licenses', 'Travel Expenses',
'Contract Wages', 'Revenue',
'Marketing Fees', 'Subscriptions',
'Software' ]
@category_choices.sort!
end
end
The Items controller
controllers/items_controller.rb
class ItemsController < ApplicationController
before_action :set_item, only: %i[ show edit update destroy ]
# GET /items or /items.json
def index
@items = Item.all
end
# GET /items/1 or /items/1.json
def show
end
# GET /items/new
def new
end
# GET /items/1/edit
def edit
end
def add_item
@act = Activity.find(params[:activity_id])
@act.items.create(
activity: @act
)
end
# POST /items or /items.json
# POST /items or /items.json
def create
@item = Item.new(item_params)
respond_to do |format|
if @item.save
format.html { redirect_to edit_activity_path(activity_id), notice: "Item was successfully created." }
#format.json { render :show, status: :created, location: @item }
else
format.html { render :new, status: :unprocessable_entity }
#format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /items/1 or /items/1.json
def update
respond_to do |format|
if @item.update(item_params)
format.html { redirect_to item_url(@item), notice: "Item was successfully updated." }
format.json { render :show, status: :ok, location: @item }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /items/1 or /items/1.json
def destroy
@item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: "Item was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_item
@item = Item.find(params[:id])
end
# Only allow a list of trusted parameters through.
def item_params
params.require(:item).permit(:activity_id, :item_amount, :vendor, :expense_category, :transaction_type)
end
end
The application.js file:
app/javascript/application.js
import "@hotwired/turbo-rails"
import "controllers"
import "trix"
import "@rails/actiontext"
import * as bootstrap from "bootstrap"
import "custom/main"
import "vanilla-nested";
the importmap.rb
config/importmap.rb
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"
pin "vanilla-nested", to: "vanilla_nested.js", preload: true
pin_all_from "app/javascript/custom", under: "custom"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
