Mantine入門6 ブログ概要入力フォームを作成しよう
前回のカード内容(タイトル、日付、タグ、概要)と、カードからリンクされる記事本体へのリンクを設定するフォームのページを作成します。
カードの内容は違う記事だとしても同じJSONファイルに記載していきます。カードをタグや日付で並べ替えたり、切り替えたりします。
(記事の一時保存、記事作成ページは、後で追加します。記事自体は、記事ごとに個別にJSONファイルに保存します。)
フォームの作成
タイトルはTextInput、タグはMultiSelect、概要はTextArea
日付、ブログ本体のファイル名(リンク先)は自動入力とします。
import { Paper, TextInput, MultiSelect,Textarea } from "@mantine/core";
import { NextPage } from "next";
const data = [
{ value: 'react', label: 'React' },
{ value: 'next', label: 'Next.js' },
{ value: 'python', label: 'python' },
];
const WriteBlog:NextPage = () =>{
return(
<>
<Paper shadow="md" m="md" p="sm">
<TextInput mt="sm"
label="タイトル" withAsterisk
placeholder="タイトルを入力してください"
/>
<MultiSelect mt="sm"
label="カテゴリ"
placeholder="タグを選択してください。(複数可)"
data={data}
/>
<Textarea mt="sm"
label="概要"
placeholder="概要(目的と結果)を記載してください"
autosize
minRows={2}
/>
</Paper>
<Group position="right">
<Button mt="sm" >送信</Button>
</Group>
</>
)
}
export default WriteBlog
以下のようなフォームができました。
文字の制限や抜け漏れなどを確認するuseFormを使っていきます。
準備
import { useForm } from "@mantine/form";
....
const WriteBlog:NextPage = () =>{
const cardform = useForm(
{
initialValues:{
title:'',//TextInputのvalueは文字列
tag:[''],//MultiSelectのvalueは文字列の配列
abstract:'',//Inputareaのvalueは文字列
},
}
)
......
まずは、上記のように最終的にフォームから入手したいJSONフォーマットをinitalValuesに定義します。コレをuseFormの関数に渡してformオブジェクトを生成します。
Inputとの紐付け
次に、先ほど定義したJsonフォーマットを含んだuseFormオブジェクトformと、InputText,MultiSelect,Textareaと紐付けします。下記のように、それぞれのJSXタグの中に、…from.getInputProps('jsonキー’)のスプレッド構文を埋め込みます。
<TextInput mt="sm"
label="タイトル" withAsterisk
placeholder="タイトルを入力してください"
{...cardform.getInputProps('title')}
/>
<MultiSelect mt="sm"
label="カテゴリ"
placeholder="タグを選択してください。(複数可)"
data={data}
{...cardform.getInputProps('tag')}
/>
<Textarea mt="sm"
label="概要"
placeholder="概要(目的と結果)を記載してください"
autosize
minRows={2}
{...cardform.getInputProps('abstract')}
/>
コレで、useFormのさまざまな関数をInputに反映できます。
値のセット
たとえば、フォームの値を設定できます。
以下のようなボタンイベントハンドラ内でsetFieldValue関数を使ってみます。ただ、この機能はあまり使わないでしょう。パスワードの自動割り当てなどで使う用途があるかもしれません。
const buttonHandler = () =>{
cardform.setFieldValue('title',"aaaa")
cardform.setFieldValue('tag',["next","python"])
cardform.setFieldValue('abstract','setFieldValueで入力')
}
・・・
<Button mt="sm" onClick={buttonHandler}>送信</Button>
値のリセット
reset関数でinitialValuesの値をセットし、入力エラーを解除します。間違えて押した時のことを考えると、これもあまり使わないかもしれません。
<Button mt="sm" onClick={()=>{cardform.reset()}}>リセット</Button>
値のバリデーション
フォームのバリデーションは、以下のように、useFormの中に、validateオブジェクトを定義します。定義の方法は、initalValuesの中で定義した変数をキーとして、値として、valueを受け取り、正常時にはnullを返し、異常時には文字列を返す関数を設定します。正常、異常の条件はスクリプトで記述します。
タイトルには下記のようなシンプルな3項演算子でバリデーションを定義します。
const cardform = useForm(
{
initialValues:{
title:'',//TextInputのvalueは文字列
tag:[''],//MultiSelectのvalueは文字列の配列
abstract:'',//Inputareaのvalueは文字列
},
validate:{
title:(value) => (
value.length < 1
? '必須入力です。'
: null),
},
}
)
複雑な条件の時は、関数にすることもできます。useFomeにvalidateInputOnChange: true を加えると、valueが変わるたびに評価されます。
const validnum = (value:string) => {
let ret = null
if(value.length < 10)
{
ret = "10文字以上で入力してください'"
}
if(value.length > 300)
{
ret = "300文字以下で入力してください。"
}
return ret
}
const WriteBlog:NextPage = () =>{
const cardform = useForm(
{
initialValues:{
title:'',//TextInputのvalueは文字列
tag:[''],//MultiSelectのvalueは文字列の配列
abstract:'',//Inputareaのvalueは文字列
},
validate:{
title:(value) => (
value.length < 1
? '必須入力です。'
: null),
abstract:(value)=>(validnum(value)),
},
validateInputOnChange: true ,
}
)
バリデーションを実行するタイミングは、通常、formタグ内に定義しtype="submit"のボタンがクリックされた時です。
const WriteBlog:NextPage = () =>{
const cardform = useForm(
{
initialValues:{
title:'',//TextInputのvalueは文字列
tag:[''],//MultiSelectのvalueは文字列の配列
abstract:'',//Inputareaのvalueは文字列
},
validate:{
title:(value) => (
value.length < 1
? '必須入力です。'
: null),
abstract:(value)=>(validnum(value)),
},
validateInputOnChange: true ,
}
)
return(
<>
<Paper shadow="md" m="md" p="sm">
<form onSubmit={cardform.onSubmit((value)=>console.log(value))}>
<TextInput mt="sm"
label="タイトル" withAsterisk
placeholder="タイトルを入力してください"
{...cardform.getInputProps('title')}
/>
<MultiSelect mt="sm"
label="カテゴリ"
placeholder="タグを選択してください。(複数可)"
data={data}
{...cardform.getInputProps('tag')}
/>
<Textarea mt="sm"
label="概要" withAsterisk
placeholder="概要(目的と結果)を記載してください"
autosize
minRows={2}
{...cardform.getInputProps('abstract')}
/>
<Group position="right">
<Button mt='sm' type="submit">送信</Button>
</Group>
</form>
</Paper>
</>
)
}
export default WriteBlog
バリデーションに引っ掛かっていると、
<form onSubmit={cardform.onSubmit((value)=>console.log(value))}>
のログ出力が出てきません。バリデーションに引っ掛かっていないければ、ログに値が表示されます。ここでデータベースなどに情報を書き込む流れ(バックエンド処理)になります。