Struts2でテンプレートエンジンであるJSPを使うとフォーム画面が崩れてしまいました。
どんなことが起こったかというと、仕様としては<input type="text">のような入力オブジェクトがフォームの上部に来て、直下にファイルのアップロードや登録ボタンを配置したかったです。
試しに下記のJSPファイルを作成しました。
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.1 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- 文字化け防止処理 start-->
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page pageEncoding="UTF-8" %>
<!-- 文字化け防止処理 end-->
<%@taglib prefix="s" uri="/struts-tags" %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>Hello World</title>
<link href="<s:url value='/styles/common/common.css'/>" rel="stylesheet" type="text/css" media="all"/>
<link href="<s:url value='/styles/bootstrap/bootstrap.min.css'/>" rel="stylesheet" type="text/css" media="all"/>
<!--<s:head />-->
</head>
<body>
Hello <s:property value="name"/>, today is <s:property value="dateNow" /><br/>
<!-- 追加 -->
<s:form id="userForm" action="userRegister" method="post" enctype="multipart/form-data">
<div>
<!-- 1.ユーザ名 -->
<s:textfield
label="ユーザ名"
name="userName"
required="true"/>
<!-- 2. メールアドレス -->
<s:textfield
label="メールアドレス"
name="email"
required="true"/>
<!-- 3. パスワード -->
<s:password
label="パスワード"
name="password"
required="true"/>
<!-- 4. 性別(ラジオボタン) -->
<s:radio
label="性別"
name="gender"
list="#{'M':'男性','F':'女性'}"/>
<!-- 5. 会社拠点(リストボックス) -->
<s:select
label="会社拠点"
name="office"
list="#{
'':'選択してください。',
'東京都':'東京都',
'埼玉県':'埼玉県',
'神奈川県':'神奈川県',
'千葉県':'千葉県',
'栃木県':'栃木県'
}"/>
<!-- 7. 管理者権限 -->
<s:checkbox label="管理者" name="adminRole" fieldValue="true" />
</div>
<div>
<!-- 6. 写真アップロード(最大3枚) -->
<div id="fileUploads">
<p>写真:<input type="file" name="photos"/></p>
</div>
<input type="button" value="ファイル追加" onClick="addFileInput();"/>
<br />
<!-- 送信ボタン -->
<input type="button" value="登録確認" onClick="goConfirm();"/>
</div>
</s:form>
<script type="text/javascript">
function goConfirm(){
document.getElementById("userForm").submit();
}
// ファイルアップロード処理
function addFileInput(){
var div = document.getElementById("fileUploads");
var p = document.createElement("p");
p.innerHTML = '写真:<input type="file" name="photos"/>';
div.appendChild(p);
}
</script>
</body>
</html>
👆だと、フォーム画面の上部に①ファイルのアップロード機能や登録ボタンが来てしまい、その下に<input>タグの入力オブジェクトが配置されます。
(原因)
原因は Struts2 の<s:form>がデフォルトで「table レイアウト(theme=xhtml)」を生成していることです。
そのため、
■<s:textfield> や<s:checkbox>→ <table><tr><td>…</td></tr></table>
■途中に書いた 生HTML(<div> や <input>) → table の外 or 想定外の位置
になり、「フォームの下に書いたのに下に来ない」という現象が起きます。
解決策(Struts2ではこれが定石)
✅ 方法①:theme="simple" を使う(最も簡単・おすすめ)
s:form にtheme="simple"を指定すると、
table を使わず、書いた順にHTMLが出力されます。
<s:form
id="userForm"
action="userRegister"
method="post"
enctype="multipart/form-data"
theme="simple">
// 処理
</s:form>
全体イメージは下記👇
<s:form id="userForm" action="userRegister" method="post"
enctype="multipart/form-data" theme="simple">
<p>ユーザ名:<s:textfield name="userName"/></p>
<p>メールアドレス:<s:textfield name="email"/></p>
<p>パスワード:<s:password name="password"/></p>
<p>性別:
<s:radio name="gender" list="#{'M':'男性','F':'女性'}"/>
</p>
<p>会社拠点:
<s:select name="office"
list="#{'':'選択してください。','東京都':'東京都','埼玉県':'埼玉県'}"/>
</p>
<p><s:checkbox name="adminRole"/> 管理者</p>
<hr/>
<!-- フォーム下部 -->
<div id="fileUploads">
<p>写真:<input type="file" name="photos"/></p>
</div>
<input type="button" value="ファイル追加" onclick="addFileInput();" />
<br/><br/>
<input type="button" value="登録確認" onclick="goConfirm();" />
</s:form>