创建联系表单页面并通过 Ajax 提交表单请求数据
回顾下上篇教程更新主题后的博客系统,可以看到顶部右上角导航菜单有两个链接,分别指向关于页面和联系表单页面:
对应的 HTML 模板代码位于 resources/views/header.php
中:
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="/">首页</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about">关于</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/contact">联系</a>
</li>
</ul>
</div>
现在我们来为这两个页面定义 URL 路由和对应的页面渲染逻辑。在 app/routes/web.php
中注册路由:
$router->register('get', 'about', 'HomeController@about');
$router->register(['get', 'post'], 'contact', 'HomeController@contact');
我们将请求处理逻辑都放到了 HomeController
控制器对应的 Action 方法中实现。
1、关于页面
对于关于页面而言,我们直接对应的路由定义为重定向到外部链接:
class HomeController extends Controller
{
...
// 关于页面
public function about()
{
$response = new Response('', 301, ['Location' => 'https://xueyuanjun.com/about-us']);
$response->send();
}
...
}
2、渲染联系表单页面
对于联系表单页面,需要分两块处理,首先是渲染联系表单,这是一个 GET 请求:
// 联系表单页面
public function contact()
{
if ($this->request->getMethod() == 'GET') {
$pageTitle = '联系我 - ' . $this->container->resolve('app.name');
$siteName = $this->container->resolve('app.name');
$this->view->render('contact.php', compact('pageTitle', 'siteName'));
} else {
// @todo 处理表单请求数据(放到下一篇教程详细介绍)
}
}
我们通过 $this->request->getMethod()
获取 HTTP 请求方法,并以此作为依据进行下一步处理:如果是 GET 请求,则渲染联系表单页面,如果是 POST 请求,则处理表单请求数据。
渲染联系表单页面对应的视图模板是 resources/views/contact.php
,我们创建这个视图文件,并初始化代码如下:
<?php include 'header.php';?>
<!-- Page Header -->
<header class="masthead" style="background-image: url('/image/contact.jpg')">
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div class="page-heading">
<h1>联系我</h1>
<span class="subheading">你有问题?我有答案。</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<p>你可以通过填写并提交下面的表单给我发送反馈消息,我会尽快给你回复!</p>
<form name="sentMessage" id="contactForm" novalidate>
<div class="control-group">
<div class="form-group floating-label-form-group controls">
<label>用户名</label>
<input type="text" class="form-control" placeholder="Name" id="name" required data-validation-required-message="请输入你的用户名">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="control-group">
<div class="form-group floating-label-form-group controls">
<label>邮箱地址</label>
<input type="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="请输入你的邮箱">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>手机号码</label>
<input type="tel" class="form-control" placeholder="Phone" id="phone" required data-validation-required-message="请输入你的手机号码">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="control-group">
<div class="form-group floating-label-form-group controls">
<label>消息内容</label>
<textarea rows="5" class="form-control" placeholder="Message" id="message" required data-validation-required-message="请输入你要发聩的消息内容"></textarea>
<p class="help-block text-danger"></p>
</div>
</div>
<br>
<div id="success"></div>
<button type="submit" class="btn btn-primary" id="sendMessageButton">发送</button>
</form>
</div>
</div>
</div>
<hr>
<?php include 'footer.php';?>
<script src="/js/contact.js"></script>
</body>
</html>
这里主要包含的是一个联系表单,参照 node_modules/startbootstrap-clean-blog/contact.html
编写即可。
3、提交表单请求
在上面的视图模板中,可以看到最后额外引入了 /js/contact.js
文件,这个文件是联系表单页面需要额外用到的 JavaScript 脚本文件,目前还不存在,需要编写对应的前端处理代码,并通过 Laravel Mix 组件编译打包生成。
在 resources/js
目录下新建 contact.js
,并初始化代码如下:
require('./bootstrap')
require('startbootstrap-clean-blog/js/jqBootstrapValidation')
$(function() {
$("#contactForm input,#contactForm textarea").jqBootstrapValidation({
preventSubmit: true,
submitError: function($form, event, errors) {
// additional error messages or events
},
submitSuccess: function($form, event) {
event.preventDefault(); // prevent default submit behaviour
// get values from FORM
var name = $("input#name").val();
var email = $("input#email").val();
var phone = $("input#phone").val();
var message = $("textarea#message").val();
var firstName = name; // For Success/Failure Message
// Check for white space in name for Success/Fail message
if (firstName.indexOf(' ') >= 0) {
firstName = name.split(' ').slice(0, -1).join(' ');
}
$this = $("#sendMessageButton");
$this.prop("disabled", true); // Disable submit button until AJAX call is complete to prevent duplicate messages
$.ajax({
url: "/contact",
type: "POST",
data: {
name: name,
phone: phone,
email: email,
message: message
},
cache: false,
success: function(resp) {
// Success message
$('#success').html("<div class='alert alert-success'>");
$('#success > .alert-success').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×")
.append("</button>");
$('#success > .alert-success')
.append("<strong>消息已发送。</strong>");
$('#success > .alert-success')
.append('</div>');
//clear all fields
$('#contactForm').trigger("reset");
},
error: function(resp) {
// Fail message
$('#success').html("<div class='alert alert-danger'>");
$('#success > .alert-danger').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×")
.append("</button>");
$('#success > .alert-danger').append($("<strong>").text(resp.responseText));
$('#success > .alert-danger').append('</div>');
//clear all fields
$('#contactForm').trigger("reset");
},
complete: function() {
setTimeout(function() {
$this.prop("disabled", false); // Re-enable submit button when AJAX call is complete
}, 1000);
}
});
},
filter: function() {
return $(this).is(":visible");
},
});
$("a[data-toggle="tab"]").click(function(e) {
e.preventDefault();
$(this).tab("show");
});
});
/*When clicking on Full hide fail/success boxes */
$('#name').focus(function() {
$('#success').html('');
});
这里我们首先通过 require('./bootstrap')
引入 jQuery 及 Bootstrap 模块,然后引入 jqBootstrapValidation
组件对表单请求数据进行简单验证,比如字段不能为空等,最后编写了一段 jQuery 代码处理表单数据的异步提交(Ajax 请求),关于代码实现细节就不展开介绍了,重点关注 submitSuccess
的情况下,$.ajax({...})
中的处理代码。
4、访问联系表单页面
完成以上工作后,在项目根目录下的 webpack.mix.js
中添加 contact.js
编译代码:
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/contact.js', 'public/js/contact.js')
.sass('resources/sass/app.scss', 'public/css');
运行 npm run dev
重新编译打包前端代码,成功后就可以在 public/js
目录下看到 contact.js
了。
在浏览器中访问 http://localhost:9000/contact
,就可以看到联系表单页面了:
我们可以尝试提交空表单,会显示报错信息,这就是 jqBootstrapValidation
组件生效的效果:
这个处理逻辑是前端的,表单数据前端验证通过发送给后端的验证和处理逻辑,我们放到下篇教程介绍。
(全文完)
- 《Python自然语言处理》答案第一、二章
- 【 关关的刷题日记49】 Leetcode 434. Number of Segments in a String
- 自然语言处理构建文本向量空间1.百科2.源代码3.参考:
- 小爬虫之爬取豆瓣电影排行榜1.技术路线2.任务3.分析4.运行结果5.源码
- Numpy 修炼之道 (5)—— 索引和切片
- 深入理解final关键字
- Numpy 修炼之道 (4)—— 基本运算操作
- 一些APT攻击案例分享
- 浅谈命令查询职责分离(CQRS)模式
- Numpy 修炼之道 (3)—— 数据类型
- 熔断器设计模式
- 树链剖分详解
- 洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)
- 学习使用Jieba1.Jieba2. 特点3.功能4.安装5.使用6.其他中文分词工具
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Laravel 路由使用入门
- Go 数据存储篇(六):数据表之间的关联关系和关联查询
- 搭建nextcloud私有云存储网盘的教程详解
- Laravel 路由使用进阶
- 使用dig/nslookup命令查看dns解析的方法步骤
- Go 数据存储篇(七):GORM 使用入门
- 在 Linux 上使用 Multitail命令的教程
- 深入理解linux执行文件提示No such file or directory的背后原因
- Laravel 控制器:从 MVC 模式聊起
- 基于yolo5工地安全帽和禁入危险区域识别系统,附数据集
- Go 常见并发模式实现(一):调度后台处理任务的作业程序
- 路由使用进阶(二)
- linux No space left on device由索引节点(inode)爆满引发500问题
- linux中批量添加文件前缀的操作方法
- Go 常见并发模式实现(二):通过缓冲通道实现共享资源池