個人檔案頁面 CRUD 及切版
我們將會員系統基本功能開發完後,就先放置到一旁吧
先把畫面做出來,應該會比較直覺一點
今天我們要來做個人資料這個頁面(不過今天主題不會介紹到切版)
目前在程式開發時,元件化的架構越來越多人使用
元件化可以將複雜的程式碼拆分成一部份、一部份的小區塊,並且可以重複使用
所以我們要來介紹 View Component 這個套件啦!
安裝事宜可參考官方網站
假設個人頁面要元件化,該怎麼做呢
CRUD 中,new 頁面及 edit 頁面會重複使用到 form 表單
僅有按鈕不同,或者是頁面上的說明也會不太一樣
這時候我們可以把重複的 form 表單抽出來
做成一個 component
下方是我自己切的 form 表單
<h2 class="mb-10 text-2xl">新增個人檔案</h2>
<%= form_with model: @profile, url: profiles_path do |f| %>
<div class="flex items-center mb-4 field">
<%= f.label :name, '姓名' , class: 'mr-4' %><br />
<%= f.text_field :name, autocomplete: "email", class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :address, '地址' , class: 'mr-4' %><br />
<%= f.text_field :address, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :phone, '電話' , class: 'mr-4' %><br />
<%= f.phone_field :phone, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :gender, '性別' , class: 'mr-4' %><br />
<%= f.text_field :gender, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :birthday, '生日' , class: 'mr-4' %><br />
<%= f.date_field :birthday, class: 'rounded-md' %>
</div>
<%= f.submit '送出', class: 'bg-slate-500 p-2 text-white rounded-md' %>
<% end %>
我們會將 form 表單抽出來,做成 component
我們可以直接下指令來做出一個 component
指令跑完會幫我們產生一個 component 的檔案及測試檔
$ rails g component ProfileForm
create app/components/profile_form_component.rb
invoke test_unit
create test/components/profile_form_component_test.rb
invoke tailwindcss
create app/components/profile_form_component.html.erb
這時候我們來到 component 的檔案中
# components/profile_form_component.rb
class ProfileFormComponent < ViewComponent::Base
end
component 本身是個 class
我們可以用 initialize
的方式來幫他初始化
以這個例子來說,我要初始化的就會是 profile 這個實體變數
初始化的時候就能帶入 profile 的資料
# frozen_string_literal: true
class ProfileFormComponent < ViewComponent::Base
def initialize(profile: )
@profile = profile
end
end
現在我們將 new.html.erb
中的 form 表單(要元件化的區塊)貼到 component 的 html 檔案裡
# components/profile_form_component.html.erb
<%= form_with model: @profile, url: 'profile_path' do |f| %>
<div class="flex items-center mb-4 field">
<%= f.label :name, '姓名' , class: 'mr-4' %><br />
<%= f.text_field :name, autocomplete: "email", class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :address, '地址' , class: 'mr-4' %><br />
<%= f.text_field :address, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :phone, '電話' , class: 'mr-4' %><br />
<%= f.phone_field :phone, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :gender, '性別' , class: 'mr-4' %><br />
<%= f.text_field :gender, class: 'rounded-md' %>
</div>
<div class="flex items-center mb-4 field">
<%= f.label :birthday, '生日' , class: 'mr-4' %><br />
<%= f.date_field :birthday, class: 'rounded-md' %>
</div>
<%= f.submit '送出', class: 'bg-slate-500 p-2 text-white rounded-md' %>
<% end %>
接著我們回到 new.html.erb
將原本的 form 表單改以 component 帶入
# profiles/new.html.erb
<h2 class="mb-10 text-2xl">新增個人檔案</h2>
<%= render(ProfileFormComponent.new(profile: @profile)) %>
回到瀏覽器重新整理個人檔案的 new 頁面,這時候可能會出錯
uninitialized constant #<Class:0x00000001090f7d00>::ProfileFormComponent
一開始設定 component 時,要記得必須要重開 server
不然可能就會有問題喔
重開應該就能看到正常的畫面了
重複利用是元件化的特點之一
接下來我們必須要將剛剛的 component 帶入 edit 頁面中
<h2 class="mb-10 text-2xl">編輯個人檔案</h2>
<%= render(ProfileFormComponent.new(profile: @profile)) %>
接下來,我們可以重整瀏覽器
看到以下畫面就是成功囉
這樣我們就完成了元件化囉!
如果我們想要傳進去的是一整群資料, component 也有提供方便的用法
我們只要再 component 的 rb 檔案中加入 with_collection_parameter :profile
在 view 中使用 with_collection
方法就可以像 each 的方式,帶入一筆一筆的資料囉
<%= render(ProfileComponent.with_collection(profile: @profiles)) %>
我們可以把 component 想像成是 Controller 跟 View
component.rb
就是 Controller
component.html.erb
就是 Ciew
component 要載入時,
component class 就會 new 出一個 component 來,
並且載入初始化設定(initialize 在此時就會執行)
最後再把這些資料帶入 view 中