"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

GO言語(golang)/Webアプリケーション(3)「gin」&各入力部品からの値受け取りのポイント

f:id:arakan_no_boku:20210412005751p:plain

目次

HTML5のいろいろな入力部品

HTML5の入力部品(inputとSelectとtextarea)からの値受け取りと表示をやります。

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

特に最初にはまりやすい以下の3つ。

  • textarea内の改行の受け取りと表示
  • Selectでmultipleにして、複数選択した結果の受け取りと表示
  • checkboxでOff(未チェック)状態の受け取り判断

についても、試して整理しておきます。

サンプル入力画面イメージとHTML

今回使うサンプル入力画面の表示イメージです。

f:id:arakan_no_boku:20210611225020p:plain

日付入力は、選択すると以下のようにカレンダーが開きます。

f:id:arakan_no_boku:20210611225220p:plain

さて、この画面を実現するHTMLです。

<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<meta name="description" content="HTML5 exsample" />
		<meta name="author" content="boku" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<link rel="stylesheet" href="https://fonts.xz.style/serve/inter.css" />
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css" />
		<title>Hello</title>
	</head>
	<body>
		<h1>{{.title}}</h1>
		<form method="POST" action="/">
			<table>
				<tr>
					<th style="width: 20%">テキストボックス</th>
					<td style="width: 80%"><input type="text" name="sampletext" style="width: 100%; border: solid 1px" /></td>
				</tr>
				<tr>
					<th style="width: 20%">日付入力</th>
					<td style="width: 80%"><input type="date" name="sampledate" style="width: 100%; border: solid 1px" /></td>
				</tr>
				<tr>
					<th style="width: 20%">SELECT</th>
					<td style="width: 80%">
						<select  name="sampleselect" style="width: 100%;border: solid 1px" />
							<option value="1">これを選ぶと、1の値が取得できるはず</option>
							<option value="2">これを選ぶと、2の値が取得できるはず</option>
							<option value="3">これを選ぶと、3の値が取得できるはず</option>
							<option value="4">これを選ぶと、4の値が取得できるはず</option>
						</select>	
					</td>
				</tr>
				<tr>
					<th style="width: 20%">SELECT複数</th>
					<td style="width: 80%">
						<select  name="samplemulti" multiple size="3" style="width: 100%;border: solid 1px" />
							<option value="1">これを選ぶと、1の値が取得できるはず</option>
							<option value="2">これを選ぶと、2の値が取得できるはず</option>
							<option value="3">これを選ぶと、3の値が取得できるはず</option>
							<option value="4">これを選ぶと、4の値が取得できるはず</option>
						</select>	
					</td>
				</tr>
				<tr>
					<th style="width: 20%">チェックボックス</th>
					<td style="width: 80%"><input type="checkbox" name="samplecheck" />チェックボックスの状態を取得するサンプル</td>
				</tr>
				<tr>
					<th style="width: 20%">ラジオボタン</th>
					<td style="width: 80%">
						<input type="radio" name="sampleradio" value="1" checked /><label>選択肢1</label>
						<input type="radio" name="sampleradio" value="2" /><label>選択肢2</label>
						<input type="radio" name="sampleradio" value="3" /><label>選択肢3</label>
					</td>
				</tr>
				<tr>
					<th style="width: 20%">スライダー</th>
					<td style="width: 80%">
						<input type="range" name="samplerange" style="width: 100%" />
					</td>
				</tr>
				<tr>
					<th style="width: 20%">複数行入力</th>
					<td style="width: 80%">
						<textarea name="samplearea" style="width: 100%;height:55px;border: solid 1px"></textarea>
					</td>
				</tr>
				<tr>
					<td colspan="2"><input type="submit" value="画面遷移" /></td>
				</tr>
			</table>
		</form>
	</body>
</html>


 

輪郭をはっきりさせるのに、borderとかつけたりしてますが、ほぼ、まんま使っているだけです。

HTML5だと、JavaScriptとかを使わず、ここまでの入力具品が使えるのです。

なお、CSSは、クラス指定なしで使えるnew.cssを使っています。

newcss.net

入力値の受け取りと結果のHTML表示

POSTで受け取ります。

POSTで値を受け取りファンクションの定義やrouter部分の定義などについては、前回に書いている内容をそのまま引き続き使います。

ファンクションは「func IndexPostAction(ctx *gin.Context) {」と定義していて、以下のサンプルででてくる「ctx」はこの引数です。

今回は、核入力部品ごとの値の受け取り方と、それぞれの留意点のみを書きます。

input type="text" 

特に留意点はありません。

<input type="text" name="sampletext"  />

f:id:arakan_no_boku:20210611233605p:plain

であれば、

txt := ctx.PostForm("sampletext")

でうけて、txtにセットされた文字列を使います。

input type="date" 

フォーマットされた日付文字列で受け取れます。

<input type="date" name="sampledate" />

f:id:arakan_no_boku:20210611233633p:plain

であれば

datetxt := ctx.PostForm("sampledate")

で「2021/06/11」という文字列を受け取れます。

あとは、文字列から日付型にコンバートするなりして使えばよい感じです。

select

シングルとマルチで受取り方を変える必要があります。

f:id:arakan_no_boku:20210611233710p:plain

以下の基本形(シングル)であれば

<select name="sampleselect" />
    <option value="1">これを選ぶと、1の値が取得できるはず</option>
    <option value="2">これを選ぶと、2の値が取得できるはず</option>
    <option value="3">これを選ぶと、3の値が取得できるはず</option>
    <option value="4">これを選ぶと、4の値が取得できるはず</option>
</select>

ふつうにPostFormで選択されている「optionのvalue値」を受け取れます。

selectedval := ctx.PostForm("sampleselect")

ところが、マルチの場合だとPostFormでは複数選択しても1つしか受け取れません。

<select name="samplemulti" multiple size="3" />

だと、複数選択された「optionのvalue値」をすべて受け取るには

selectedmulti := ctx.PostFormArray("samplemulti")

のように、PostFormArrayを使う必要があります。

input type="checkbox" 

選択されていると"on"という文字列を取得できます。

<input type="checkbox" name="samplecheck" />チェックボックスの状態を取得するサンプル

f:id:arakan_no_boku:20210611233810p:plain

であれば、

checkedtxt := ctx.PostForm("samplecheck")

で"on"という文字列を取得できます。

ただ、チェックボックスの場合、チェックOFFの状態だと何も返ってきません。

なので。

if checkedtxt == "on" {
    //
} else {
    // "off"
}

のように、offであるということを判断するロジックが必要となります。

input type="radio" 

選択された「value値」を取得します。

<input type="radio" name="sampleradio" value="1"  /><label>選択肢1</label>
<input type="radio" name="sampleradio" value="2" /><label>選択肢2</label>
<input type="radio" name="sampleradio" value="3" /><label>選択肢3</label>

で、選択肢3を選んでいたなら

f:id:arakan_no_boku:20210611233839p:plain

radiochecked := ctx.PostForm("sampleradio")

で「3」のvalue値が取得できます。

input type="range"

スライドした場所の数値が取得できます。

<input type="range" name="samplerange" />

f:id:arakan_no_boku:20210611233903p:plain

であれば。

rangeval := ctx.PostForm("samplerange")

で、20とか30のような数字が取得できます。

textarea

複数行入力可能ですが、ちょっとハマリポイントがあります。

<textarea name="samplearea" ></textarea>

でボックスを表示して、下記のように改行して複数行入力できます。

f:id:arakan_no_boku:20210611233934p:plain

これを受け取るのも

txtmulti := ctx.PostForm("samplearea")

で改行情報付きで受け取れます。

なのですが、「1行目2行目」等改行されずに結果表示されることが、よくあります。

これは、textareaの改行情報はHTML Entities という特別な文字の形式で保存されているからです。

例えば、「&NewLine;」とか「&crarr;」とか「&10;」と「&13;」とかですね。

なので、改行情報をきちんと表示するには、表示するHTML側に以下のCSS定義を追加してやる必要があります。

white-space: pre-wrap

今回のサンプルでは、tableのtdタグに以下のように追加しました。

<td style="white-space: pre-wrap">{{$value}}</td>

こうしておくと。

f:id:arakan_no_boku:20210612003255p:plain

のように表示できます。

最後に今回のサンプルのソースです

前回をベースに今回変更した「index.go」と「index.html」です。

まず「index.go」です。

package controls

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func IndexAction(ctx *gin.Context) {
	title := "GETで遷移してきたサンプル"

	type datas []string

	var darr datas
	darr = append(darr, "GETで遷移してきたときの1行目")
	darr = append(darr, "GETで遷移してきたときの2行目のテキスト")

	ctx.HTML(http.StatusOK, "index.html", gin.H{"title": title, "data": darr})

}

func IndexPostAction(ctx *gin.Context) {
	var darr []string
	title := "POSTで値を受け取るサンプル"
	txt := ctx.PostForm("sampletext")
	darr = append(darr, txt)
	datetxt := ctx.PostForm("sampledate")
	darr = append(darr, datetxt)
	selectedval := ctx.PostForm("sampleselect")
	darr = append(darr, selectedval)
	selectedmulti := ctx.PostFormArray("samplemulti")
	var tmp string = "複数選択:"
	for _, v := range selectedmulti {
		darr = append(darr, tmp+string(v))
	}
	checkedtxt := ctx.PostForm("samplecheck")
	if checkedtxt == "on" {
		darr = append(darr, checkedtxt)
	} else {
		darr = append(darr, "off")
	}
	radiochecked := ctx.PostForm("sampleradio")
	darr = append(darr, radiochecked)
	rangeval := ctx.PostForm("samplerange")
	darr = append(darr, rangeval)
	txtmulti := ctx.PostForm("samplearea")
	darr = append(darr, txtmulti)
	ctx.HTML(http.StatusOK, "index.html", gin.H{"title": title, "data": darr})
}

次は「index.html」です。 

<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<meta name="description" content="HTML5 exsample" />
		<meta name="author" content="boku" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<link rel="stylesheet" href="https://fonts.xz.style/serve/inter.css" />
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css" />
		<title>Hello</title>
	</head>
	<body>
		<h1>{{.title}}</h1>
		<table>
			{{range $index,$value := .data}}
			<tr>
				<th>インデックス{{$index}}</th>
				<td style="white-space: pre-wrap">{{$value}}</td>
			</tr>
			{{end}}
			<tr>
				<td colspan="2"><a href="/inputSample?title=何かを入力するサンプル">入力サンプルの画面に遷移します。</a></td>
			</tr>
		</table>
	</body>
</html>

最後に結果の表示例です。

f:id:arakan_no_boku:20210611234145p:plain

ではでは。