Tiếp nối phần 1 khi chúng ta đã hoàn thành được 1 nửa chặng đường khi đã hoàn thành xong các yêu cầu:
- tạo checkbox
- submit có dạng :
{categories: [1, 2, 3, 4]
- multi checkbox
bài viết này chúng ta sẽ hoàn thành các yêu cầu còn lại.
Yêu cầu:
- tạo form cho 2 loại input text và checkbox + submit button
- dữ liệu khi submit form có dạng (chỉ cần console.log trong hàm thực thi):
{categories: [1, 2, 3, 4], meta: ["a", "b", "c"]}
- meta ko được chứa dữ liệu rỗng
- cho phép add or remove input text
- multi checkbox
Start!!!
Mình sử dụng code của phần 1, nên các bạn nào mới có thể quay lại phần 1 và xem lại code giúp mình nhé
form.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token operator">...</span> <span class="token comment">//tạo 1 state với số lượng input</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>inputs<span class="token punctuation">,</span> setInputs<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> content<span class="token punctuation">:</span> <span class="token string">""</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">...</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> onAddClick <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">onRemoveClick</span> <span class="token operator">=</span> index <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token operator">...</span> <span class="token operator"><</span>Grid container direction<span class="token operator">=</span><span class="token string">"column"</span><span class="token operator">></span> <span class="token operator"><</span>FormComponent categories<span class="token operator">=</span><span class="token punctuation">{</span>categories<span class="token punctuation">}</span> inputs<span class="token operator">=</span><span class="token punctuation">{</span>inputs<span class="token punctuation">}</span> onAddClick<span class="token operator">=</span><span class="token punctuation">{</span>onAddClick<span class="token punctuation">}</span> onRemoveClick<span class="token operator">=</span><span class="token punctuation">{</span>onRemoveClick<span class="token punctuation">}</span> handleChange<span class="token operator">=</span><span class="token punctuation">{</span>handleChange<span class="token punctuation">}</span> handleSubmit<span class="token operator">=</span><span class="token punctuation">{</span>handleSubmit<span class="token punctuation">}</span> setInputs<span class="token operator">=</span><span class="token punctuation">{</span>setInputs<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> |
FormComponent.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <span class="token operator">...</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> DynamicInput <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./DynamicInput"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> CategoryType<span class="token punctuation">,</span> InputType <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"../types/form"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> FormComponent <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> inputs<span class="token punctuation">,</span> onAddClic onRemoveClick<span class="token punctuation">,</span> setInputs <span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span> inputs<span class="token punctuation">:</span> InputType<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> onAddClick<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span> onRemoveClick<span class="token punctuation">:</span> <span class="token punctuation">(</span>index<span class="token punctuation">:</span> number<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span> setInputs<span class="token punctuation">:</span> <span class="token punctuation">(</span>value<span class="token punctuation">:</span> InputType<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span><span class="token operator">></span> <span class="token operator"><</span>form onSubmit<span class="token operator">=</span><span class="token punctuation">{</span>handleSubmit<span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator">...</span> <span class="token operator"><</span>Grid container direction<span class="token operator">=</span><span class="token string">"column"</span><span class="token operator">></span> <span class="token operator"><</span>Grid item<span class="token operator">></span> <span class="token operator"><</span>h3<span class="token operator">></span>Meta<span class="token operator"><</span><span class="token operator">/</span>h3<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token operator"><</span>Grid container direction<span class="token operator">=</span><span class="token string">"column"</span><span class="token operator">></span> <span class="token punctuation">{</span>inputs<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span>input<span class="token punctuation">:</span> InputType<span class="token punctuation">,</span> index<span class="token punctuation">:</span> number<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>DynamicInput key<span class="token operator">=</span><span class="token punctuation">{</span>input<span class="token punctuation">.</span>id<span class="token punctuation">}</span> onRemoveClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token function">onRemoveClick</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token operator"><</span>Grid container justify<span class="token operator">=</span><span class="token string">"center"</span> style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> marginTop<span class="token punctuation">:</span> <span class="token number">20</span><span class="token punctuation">,</span> marginBottom<span class="token punctuation">:</span> <span class="token number">20</span> <span class="token punctuation">}</span><span class="token punctuation">}</span> xs<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">10</span><span class="token punctuation">}</span> <span class="token operator">></span> <span class="token operator"><</span>Button variant<span class="token operator">=</span><span class="token string">"outlined"</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>onAddClick<span class="token punctuation">}</span><span class="token operator">></span> Add <span class="token operator"><</span><span class="token operator">/</span>Button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token comment">//button submit</span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>form<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span><span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
InputType
1 2 3 4 5 6 7 | <span class="token operator">...</span> <span class="token keyword">export</span> type InputType <span class="token operator">=</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> number<span class="token punctuation">;</span> content<span class="token punctuation">:</span> string<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Và cuối cùng là DynamicInput
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Grid<span class="token punctuation">,</span> OutlinedInput<span class="token punctuation">,</span> Button <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"@material-ui/core"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> DynamicInput <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> onRemoveClick <span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> onRemoveClick<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Grid container spacing<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">}</span> alignItems<span class="token operator">=</span><span class="token string">"center"</span><span class="token operator">></span> <span class="token operator"><</span>Grid item xs<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">10</span><span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>OutlinedInput id<span class="token operator">=</span><span class="token string">"my-input"</span> style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> marginBottom<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> marginTop<span class="token punctuation">:</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">}</span> placeholder<span class="token operator">=</span><span class="token string">"Type any thing in here"</span> fullWidth required <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token operator"><</span>Grid item xs<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>Button variant<span class="token operator">=</span><span class="token string">"outlined"</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>onRemoveClick<span class="token punctuation">}</span><span class="token operator">></span> Remove <span class="token operator"><</span><span class="token operator">/</span>Button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Grid<span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
ok chúng ta đã có giao diện như sau
Tiếp theo như đề bài là ta có thể thêm input mỗi khi click button Add
và remove input đó đi với button Remove
, ta sửa lại 2 function ở trên nhé
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token operator">...</span> <span class="token keyword">const</span> onAddClick <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">//chèn thêm 1 object input mới mỗi khi click butotn `Add`</span> <span class="token keyword">let</span> newInput<span class="token punctuation">:</span> InputType <span class="token operator">=</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> inputs<span class="token punctuation">.</span>length<span class="token punctuation">,</span> content<span class="token punctuation">:</span> <span class="token string">""</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">setInputs</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">...</span>inputs<span class="token punctuation">,</span> newInput<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">//xóa input đó đi với vị trí index được click</span> <span class="token keyword">const</span> <span class="token function-variable function">onRemoveClick</span> <span class="token operator">=</span> index <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">let</span> newInputs <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>inputs<span class="token punctuation">]</span><span class="token punctuation">;</span> newInputs<span class="token punctuation">.</span><span class="token function">splice</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setInputs</span><span class="token punctuation">(</span>newInputs<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token operator">...</span> |
Và đây là kết quả
Vậy là đã gần xong rồi đó, nhưng bất chợt nhận ra là nếu khi ta có nhiều hơn 1 input thì khi muốn sửa text của input 1 và input 2 thì sao? với code hiện tại sẽ như thế nào? giá trị sẽ vào state inputs
ra sao? Chắc chắn nếu hiện tại bạn chạy project nên và nhập input, state inputs
field content của các input sẽ không có nội dung gì cả, vậy để fix lỗi này ta làm như sau:
thêm hàm onChange cho DynamicInput
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token operator">...</span> <span class="token operator"><</span>DynamicInput key<span class="token operator">=</span><span class="token punctuation">{</span>input<span class="token punctuation">.</span>id<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span>e<span class="token punctuation">:</span> React<span class="token punctuation">.</span>ChangeEvent<span class="token operator"><</span>HTMLInputElement<span class="token operator">></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token comment">//set lại value input mỗi khi thay đổi dựa theo index của input được chọn </span> <span class="token comment">//với index đã có trong state `inputs`</span> <span class="token function">setInputs</span><span class="token punctuation">(</span> inputs<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> inputSelector<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> inputSelector<span class="token punctuation">)</span> value<span class="token punctuation">.</span>content <span class="token operator">=</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token keyword">return</span> value<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> onRemoveClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token function">onRemoveClick</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator">...</span> |
DynamicInput
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token operator">...</span> <span class="token keyword">export</span> <span class="token keyword">const</span> DynamicInput <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span> onChange<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span> onChange<span class="token punctuation">:</span> <span class="token punctuation">(</span>event<span class="token punctuation">:</span> object<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>OutlinedInput <span class="token operator">...</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span>onChange<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Vậy là đã xử lý xong, handle lại chút function onSubmit để thấy kết quả nào
1 2 3 4 5 6 7 | <span class="token keyword">const</span> <span class="token function-variable function">handleSubmit</span> <span class="token operator">=</span> event <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"categories"</span><span class="token punctuation">,</span> categoriesSelector<span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"-------------------------------"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"meta"</span><span class="token punctuation">,</span> <span class="token function">getMeta</span><span class="token punctuation">(</span>inputs<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> event<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
function helper getMeta
1 2 3 4 5 6 7 8 | <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">getMeta</span> <span class="token operator">=</span> arrInputs <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> result <span class="token operator">=</span> arrInputs<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>input <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> input<span class="token punctuation">.</span>content<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Run lại và xem kết quả xem đã đúng với yêu cầu đề bài chưa nào
Và đây là Source code của cả 2 phần.
Have a nice day!
Welcome to ReactJS!!!