Skip to content

Commit b88fecc

Browse files
committed
Initial Commit
1 parent c12719f commit b88fecc

13 files changed

Lines changed: 220 additions & 1 deletion

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module Searches
2+
class ProductsController < ApplicationController
3+
def index
4+
@products = Product.where(filter_by_company)
5+
render json: @products.to_json
6+
end
7+
8+
private
9+
10+
def filter_by_company
11+
return {} unless params[:company_id].present?
12+
13+
{ company_id: params[:company_id] }
14+
end
15+
end
16+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Controller } from "@hotwired/stimulus"
2+
import TomSelect from "tom-select"
3+
4+
// Connects to data-controller="select"
5+
export default class extends Controller {
6+
connect() {
7+
new TomSelect(this.element)
8+
}
9+
10+
disconnect() {
11+
if (this.element.tomselect) {
12+
this.element.tomselect.destroy()
13+
}
14+
}
15+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Controller } from "@hotwired/stimulus"
2+
import TomSelect from "tom-select"
3+
4+
// Connects to data-controller="select-with-dependent"
5+
6+
export default class extends Controller {
7+
static values = {
8+
url: String,
9+
param: "id",
10+
target: String,
11+
target_name: "name",
12+
target_value: "id"
13+
}
14+
15+
connect() {
16+
new TomSelect(this.element)
17+
}
18+
19+
disconnect() {
20+
if (this.element.tomselect) {
21+
this.element.tomselect.destroy()
22+
}
23+
}
24+
25+
update() {
26+
const url = new URL(this.urlValue, window.location.origin)
27+
url.searchParams.set(this.paramValue, this.element.value)
28+
fetch(url, {
29+
headers: { Accept: "application/json" }
30+
})
31+
.then(response => response.json())
32+
.then(data => {
33+
const target = document.getElementById(this.targetValue)
34+
if (target) {
35+
const valueKey = this.targetValueValue
36+
const nameKey = this.targetNameValue
37+
if (target.tomselect) {
38+
target.tomselect.clearOptions()
39+
data.forEach(option => {
40+
target.tomselect.addOption({ value: option[valueKey], text: option[nameKey] })
41+
})
42+
target.tomselect.refreshOptions(false)
43+
} else {
44+
target.innerHTML = ""
45+
data.forEach(option => {
46+
const opt = document.createElement("option")
47+
opt.value = option[valueKey]
48+
opt.textContent = option[nameKey]
49+
target.appendChild(opt)
50+
})
51+
}
52+
}
53+
})
54+
}
55+
}

app/models/company.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Company < ApplicationRecord
2+
has_many :products, dependent: :destroy
3+
end

app/models/product.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Product < ApplicationRecord
2+
belongs_to :company
3+
end

app/views/layouts/application.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
<%# Includes all stylesheet files in app/assets/stylesheets %>
2121
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
22+
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.4.3/dist/css/tom-select.css" rel="stylesheet">
2223
<%= javascript_importmap_tags %>
2324
</head>
2425

app/views/welcome/index.html.erb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
<div>
22
<h1 class="font-bold text-4xl">Welcome#index</h1>
33
<p>Find me in app/views/welcome/index.html.erb</p>
4+
5+
<%= form_with url: root_path do |form| %>
6+
<%= form.label :company, "Search companies", class: "font-bold" %>
7+
8+
<%= form.select :company, Company.all.collect { |c| [c.name, c.id] },
9+
{ prompt: "Select a company" },
10+
"data-controller": "select-with-dependent",
11+
"data-action": "change->select-with-dependent#update",
12+
"data-select-with-dependent-url-value": searches_products_path,
13+
"data-select-with-dependent-target-value": "product_select",
14+
"data-select-with-dependent-param-value": :company_id,
15+
class: "mb-3" %>
16+
17+
<%= form.label :product, "Search products", class: "font-bold" %>
18+
19+
<%= form.select :product, Product.all.collect { |c| [c.name, c.id] },
20+
{ prompt: "Select a product" },
21+
"data-controller": "select",
22+
id: :product_select,
23+
class: "mb-3" %>
24+
25+
<%= form.submit "Search", class: "bg-blue-500 text-white p-2 rounded" %>
26+
<% end %>
427
</div>

config/importmap.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
pin "@hotwired/stimulus", to: "stimulus.min.js"
66
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
77
pin_all_from "app/javascript/controllers", under: "controllers"
8+
pin "tom-select", to: "https://cdn.jsdelivr.net/npm/tom-select@2.4.3/+esm"

config/routes.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
Rails.application.routes.draw do
2-
root to: 'welcome#index'
2+
namespace :searches do
3+
resources :products, only: :index
4+
end
5+
6+
root to: "welcome#index"
37
get "welcome/index"
48
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
59

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class CreateCompanies < ActiveRecord::Migration[8.0]
2+
def change
3+
create_table :companies do |t|
4+
t.string :name
5+
6+
t.timestamps
7+
end
8+
end
9+
end

0 commit comments

Comments
 (0)