As the title of the article, the content of this article will create a basic form using Material UI
, ReactJS
and Typescript
. So the first thing why do we need typescript? How does Typescript work?
- The simple reason to use typescripts is that if you want to code more tightly between
data type
, there is a synchronization between the members in the project, then use typescript. - In essence you are not learning a new programming language, but the
typescript
will be transformed viajavascript
through Babel and our code is still javascript like before.
Request:
- Create form for 2 types of text input and checkbox + submit button
- The form submission data has the form (only need console.log in the executable function):
{categories: [1, 2, 3, 4], meta: ["a", "b", "c"]}
- The meta cannot contain empty data
- Allow add or remove input text
- multi checkbox
2. Demo
Before the demo, we also need the basic knowledge:
- Basic types , you only need to spend 5 minutes to read them.
- ReactJS Form basic
- Material UI basic
- React Hooks basic
And install the dependencies as follows:
- typescript
- types / react
- types / react-dom
- material-ui / core
- material-ui / lab
Let’s start !!!
For the simple index.js
file we just need to inport the Form component we will customize now:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <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> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> ThemeProvider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@material-ui/core/styles'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> theme <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./theme'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Form <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./form'</span> <span class="token punctuation">;</span> ReactDOM <span class="token punctuation">.</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token operator"><</span> ThemeProvider theme <span class="token operator">=</span> <span class="token punctuation">{</span> theme <span class="token punctuation">}</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> ThemeProvider <span class="token operator">></span> <span class="token punctuation">,</span> document <span class="token punctuation">.</span> <span class="token function">querySelector</span> <span class="token punctuation">(</span> <span class="token string">'#root'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">import</span> React <span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <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> <span class="token keyword">from</span> <span class="token string">"@material-ui/core"</span> <span class="token punctuation">;</span> <span class="token operator">...</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">Form</span> <span class="token punctuation">(</span> <span class="token punctuation">)</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> Grid container direction <span class="token operator">=</span> <span class="token string">"column"</span> <span class="token operator">></span> Hello <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> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Okay, now let’s do the multi checkboxes first, instead of fixing the hard data checkbox, we will assume that we have a piece of data returned by the server as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">import</span> <span class="token punctuation">{</span> FormComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./components/Form"</span> <span class="token punctuation">;</span> <span class="token operator">...</span> <span class="token keyword">const</span> categories <span class="token operator">=</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> name <span class="token punctuation">:</span> <span class="token string">"ryzen 3"</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">2</span> <span class="token punctuation">,</span> name <span class="token punctuation">:</span> <span class="token string">"ryzen 5"</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">3</span> <span class="token punctuation">,</span> name <span class="token punctuation">:</span> <span class="token string">"ryzen 7"</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">4</span> <span class="token punctuation">,</span> name <span class="token punctuation">:</span> <span class="token string">"ryzen 9"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">Form</span> <span class="token punctuation">(</span> <span class="token punctuation">)</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> 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> <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> <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> |
Above, I have pass categories
through another component, the purpose is that we will handle everything in the form.tsx component and pass the implementation function back to the FormComponent
, so in my FormComponent
code will be much cleaner. .
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 | <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> FormControl <span class="token punctuation">,</span> Grid <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">import</span> <span class="token punctuation">{</span> CategoryItem <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./CategoryItem"</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> CategoryType <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> categories <span class="token punctuation">,</span> handleChange <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> categories <span class="token punctuation">:</span> CategoryType <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> handleChange <span class="token punctuation">:</span> <span class="token punctuation">(</span> categoryId <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> <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 <span class="token operator">></span> <span class="token operator"><</span> Grid item <span class="token operator">></span> <span class="token operator"><</span> h2 <span class="token operator">></span> Categories <span class="token operator"><</span> <span class="token operator">/</span> h2 <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> FormControl <span class="token operator">></span> <span class="token punctuation">{</span> categories <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> category <span class="token punctuation">:</span> CategoryType <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> CategoryItem category <span class="token operator">=</span> <span class="token punctuation">{</span> category <span class="token punctuation">}</span> handleChange <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token function">handleChange</span> <span class="token punctuation">(</span> category <span class="token punctuation">.</span> id <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> FormControl <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> |
1 2 3 4 5 | <span class="token keyword">export</span> type CategoryType <span class="token operator">=</span> <span class="token punctuation">{</span> id <span class="token punctuation">:</span> number <span class="token punctuation">;</span> name <span class="token punctuation">:</span> string <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <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> Checkbox <span class="token punctuation">,</span> FormControlLabel <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">import</span> <span class="token punctuation">{</span> CategoryType <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> CategoryItem <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> category <span class="token punctuation">,</span> handleChange <span class="token punctuation">}</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> category <span class="token punctuation">:</span> CategoryType <span class="token punctuation">;</span> handleChange <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> FormControlLabel key <span class="token operator">=</span> <span class="token punctuation">{</span> category <span class="token punctuation">.</span> id <span class="token punctuation">}</span> control <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator"><</span> Checkbox onChange <span class="token operator">=</span> <span class="token punctuation">{</span> handleChange <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> label <span class="token operator">=</span> <span class="token punctuation">{</span> category <span class="token punctuation">.</span> id <span class="token operator">+</span> <span class="token string">". "</span> <span class="token operator">+</span> category <span class="token punctuation">.</span> name <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> |
Do you find yourself adding a props handleChange
to the FormComponent? and it is used to get the clicked checkbox id. The purpose for us to get the selected checkbox values. Ok next we go through the form.tsx
and handle function handleChange
:
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 | <span class="token operator">...</span> <span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">Form</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//tạo một state chứa các checkbox được chọn</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> categoriesSelector <span class="token punctuation">,</span> setCategoriesSelectors <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> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">handleChange</span> <span class="token operator">=</span> <span class="token punctuation">(</span> currentCheckBoxSelectored <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 punctuation">{</span> <span class="token comment">//so sánh xem nếu category được chọn đã có trong state `categoriesSelector` chưa</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> categoriesSelector <span class="token punctuation">.</span> <span class="token function">includes</span> <span class="token punctuation">(</span> currentCheckBoxSelectored <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//nếu rồi thì tìm vị trí của nó theo tên phần tử `currentCheckBoxSelectored` và xóa nó đi</span> <span class="token keyword">let</span> arrCheckBoxSelectored <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token operator">...</span> categoriesSelector <span class="token punctuation">]</span> <span class="token punctuation">;</span> arrCheckBoxSelectored <span class="token punctuation">.</span> <span class="token function">splice</span> <span class="token punctuation">(</span> categoriesSelector <span class="token punctuation">.</span> <span class="token function">indexOf</span> <span class="token punctuation">(</span> currentCheckBoxSelectored <span class="token punctuation">)</span> <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">setCategoriesSelectors</span> <span class="token punctuation">(</span> arrCheckBoxSelectored <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//còn chưa thì chúng ta sẽ thêm nó vào `categoriesSelector`</span> <span class="token keyword">let</span> arrCheckBoxSelectored <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token operator">...</span> categoriesSelector <span class="token punctuation">,</span> currentCheckBoxSelectored <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token function">setCategoriesSelectors</span> <span class="token punctuation">(</span> arrCheckBoxSelectored <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 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> handleChange <span class="token operator">=</span> <span class="token punctuation">{</span> handleChange <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> |
Add Submit button to check the results, huh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token operator">...</span> <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> 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> <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> 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> <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> |
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 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> FormControl <span class="token punctuation">,</span> Grid <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">import</span> <span class="token punctuation">{</span> CategoryItem <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"./CategoryItem"</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> CategoryType <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> handleSubmit <span class="token punctuation">}</span> <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token operator">...</span> handleSubmit <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> <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 justify <span class="token operator">=</span> <span class="token string">"flex-end"</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">"contained"</span> color <span class="token operator">=</span> <span class="token string">"primary"</span> type <span class="token operator">=</span> <span class="token string">"submit"</span> <span class="token operator">></span> Submit <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> 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> |
Let’s run to see which result:
and this is the result when I first selected 3 checkboxes and then deselected with check box 2. ryzen 5