表单返回错误时,如何在同一页面显示错误?

How to display error on the same page when an error is returned by a form?

我使用以下代码构建了一个登录表单。

我使用的是 IBMi 系列原生的 CGI 版本 CGIDEV2。我正在验证 flower.cgi 程序中的 useridpassword。如果 useridpassword 得到验证,我将加载另一个 html 文件以显示 table。这完美无缺。

如果useridpassword 是错误的,我将退出程序而不写任何内容。这会导致 500 内部服务器错误。

我想使用 javascript 捕获这个 500 内部服务器错误。我尝试使用 ajax 但没有成功,因为我对 javascript.

的理解有限

实现此目标的最佳方法是什么?

<form method="POST" action="/nature/flower.cgi">
  <!-- Username input -->
  <div class="form-outline mb-4">
    <input type="text" name="userid" id="form3Example3" class="form-control form-control-lg" style="text-transform:uppercase" placeholder="Enter a valid IBMi UserID" />
    <label class="form-label" for="form3Example3">IBMi UserID</label>
  </div>
  <!-- Password input -->
  <div class="form-outline mb-3">
    <input type="password" name="passwd" id="form3Example4" class="form-control form-control-lg" placeholder="Enter password" />
    <label class="form-label" for="form3Example4">Password</label>
    <br>
  </div>
  <div class="d-flex justify-content-between align-items-center">
    <!-- Checkbox -->
    <div class="form-check mb-0">
      <input class="form-check-input me-2" type="checkbox" value="" id="form2Example3" />
      <label class="form-check-label" for="form2Example3">Remember me</label>
    </div>
    <a href="#!" class="text-body">Forgot password?</a>
  </div>
  <div class="text-center text-lg-start mt-4 pt-2">
    <button type="submit" class="btn btn-primary btn-lg" style="padding-left: 2.5rem; padding-right: 2.5rem;">Login</button>
  </div>
</form>

您无法从浏览器导航到的 URL 捕获错误。

如果您将正常的表单提交替换为 Ajax(其中发出请求 并且 响应处理为 JavaScript).

一般来说,如果您打算这样做,您还需要重写 CGI 程序,使其输出结构化数据(例如 JSON)而不是语义数据(HTML)。

这不会是一个特别小的任务。你说你试过了,这可能让你对它的范围有所了解(即远远超出了 Whosebug 问题的范围)。

更明智的方法几乎肯定是追踪 500 错误的原因并更改 CGI 程序,以便它自己捕获它。

是的,javascript 中的 fetch api 可以 post 向您的 CGI 程序形成数据并检查 500 响应代码。然后网页可以显示错误消息或 运行 form.submit() 方法实际将表单提交到服务器。

这是模拟整个过程的 PHP 和 javascript 代码。应该与 CGI 类似。关键是您将表单提交按钮从类型 'submit' 更改为类型 'button'。这样,单击提交按钮可以 运行 javascript 代码而不是将表单提交到服务器。

<?php
// site/tester/php/submit-form.php 

header("Content-type: text/html; charset:utf-8;");
?>

<?php
$userid = isset($_POST["userid"]) ? $_POST["userid"]: '' ; 
$passwd = isset($_POST["passwd"]) ? $_POST["passwd"]: '' ; 
$remember = isset($_POST["remember"]) ? $_POST["remember"]: 'off' ; 

if ( strtolower($userid) == 'alex')
{
http_response_code( 500 );
echo "$userid - invalid user name";
exit ;
}
?>

<head>

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" 
    rel="stylesheet"
    integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" 
    crossorigin="anonymous">

</head>

<body>

<div class="container">
  <div class="row mt-3">
    <div class="col-auto">
      <h1>submit form demo</h1>
    </div>
</div>


</div>

<div class="container">
  <div class="row mt-3">
    <div class="col-4">

<form method="POST" id="main-form" action="./index.php">
  <!-- Username input -->
  <div class="form-outline mb-4">
    <input type="text" name="userid" id="userid" 
    class="form-control form-control-lg" 
    value="<?= $userid ?>"
    style="text-transform:uppercase" placeholder="Enter a valid IBMi UserID" />
    <label class="form-label" for="userid">IBMi UserID</label>
  </div>
  <!-- Password input -->
  <div class="form-outline mb-3">
    <input type="password" name="passwd" id="passwd" class="form-control form-control-lg" 
    placeholder="Enter password" />
    <label class="form-label" for="passwd">Password</label>
    <br>
  </div>
  <div class="d-flex justify-content-between align-items-center">
    <!-- Checkbox -->
    <div class="form-check mb-0">
      <input class="form-check-input me-2" type="checkbox" 
      <?= ($remember == 'on' ? 'checked' : '' ) ?>
                  name="remember" id="form2Example3" />
      <label class="form-check-label" for="form2Example3">Remember me</label>
    </div>
    <a href="#!" class="text-body">Forgot password?</a>
  </div>

  <div class="text-center text-lg-start mt-4 pt-2">
    <button id="login-button" type="button" class="btn btn-primary btn-lg" 
            style="padding-left: 2.5rem; padding-right: 2.5rem;">
            Login</button>
  </div>

</form>    
    </div>
  </div>

<div id="login-errmsg-collapse" class="collapse row mt-3">
<div class="alert alert-warning" role="alert">

<p id="login-errmsg">Invalid login. User name does not exist.</p>

</div>
</div>

</div>

<div class="container">
<div class="row mt-3">

  <div class="col-auto">
    <p>userid: <?= $userid ?></p>
    <p>passwd: <?= $passwd ?></p>
    <p>remember: <?= $remember ?></p>
  </div>
</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
  integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" 
  crossorigin="anonymous"></script>
<script src="./app.js"></script>

</body>
// ./submit-form/app.js 

// enable the submit button click handler.
{
  const elem = document.getElementById('login-button');
  elem.addEventListener('click', event =>
  {
    login_click();
  });
}

// -------------------------------- login_errmsg_show ---------------------
function login_errmsg_show( respText )
{

  // show the response message in the bootstrap collapse alert box. 
  {
    const elem = document.getElementById('login-errmsg') ;
    elem.textContent = respText ;
  }

  const myCollapse = document.getElementById('login-errmsg-collapse')
  const bsCollapse = new bootstrap.Collapse(myCollapse, {
    toggle: false
  });
  bsCollapse.show( ) ;
}

// -------------------------------- login_click -------------------
async function login_click()
{
  const elem = document.getElementById('main-form');
  if (elem)
  {
    const {respText, status} = await webpage_post( ) ;
    if ( status != '500')
    {
      elem.submit();
    }
    else 
    {
      login_errmsg_show( respText ) ;
    }
  }
}

// --------------------------------- webpage_post -----------------------
async function webpage_post( )
{
  const userid = document.getElementById('userid').value ;
  const passwd = document.getElementById('passwd').value ;
  const remember = 'on' ;
 
  const url = "./index.php";

  const params = { userid, passwd, remember } ;
  const query = object_toQueryString(params);

  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: query
  });

  const respText = await response.text();
  const status = response.status ;
  console.log( respText ) ;
  return {respText, status} ;
}

// ------------------------- object_toQueryString ------------------------
function object_toQueryString(obj)
{
  const qs = Object.keys(obj)
    .map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
    .join('&');
  return qs;
}