工具表单
<h1>工具表单</h1>
<p>工具表单(<code>Dcat\Admin\Widgets\Form</code>)用来构建表单和处理提交数据,可以很方便的独立处理数据,而不需要额外注册路由。</p>
<h3>基本使用</h3>
<p>用命令<code>admin:form</code>来生成表单类文件:</p>
<pre><code class="language-bash">php artisan admin:form Setting</code></pre>
<p>将会生成表单文件<code>app/Admin/Forms/Setting.php</code></p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Widgets\Form;
use Symfony\Component\HttpFoundation\Response;
class Setting extends Form
{
// 处理表单提交请求
public function handle(array $input)
{
// dump($input);
return $this-&gt;response()-&gt;success('Processed successfully.')-&gt;refresh();
}
// 构建表单
public function form()
{
// 弹出确认弹窗
$this-&gt;confirm('您确定要提交表单吗', 'content');
$this-&gt;text('name')-&gt;required();
$this-&gt;email('email')-&gt;rules('email');
}
/**
* 返回表单数据,如不需要可以删除此方法
*
* @return array
*/
public function default()
{
return [
'name' =&gt; 'John Doe',
'email' =&gt; 'John.Doe@gmail.com',
];
}
}</code></pre>
<p>在上面的表单类里面,在<code>form</code>方法中构建表单项,使用方法和<a href="model-form.md">数据表单</a>一致,<code>default</code>方法用来给这个表单项设置默认数据。</p>
<p>在页面中填入数据提交表单之后,请求会进入到<code>handle</code>方法中,在这里可以加入你的数据处理逻辑,处理完成之后可以通过<code>success</code>或<code>error</code>方法响应数据到前端:</p>
<pre><code class="language-php"> public function handle(array $input)
{
// $input是你接收到的表单数据
// 在这里可以写你的处理逻辑
return $this-&gt;response()-&gt;success('Processed successfully.')-&gt;refresh();
}</code></pre>
<p>然后按照下面的方法将上面的表单放到你的页面中:</p>
<pre><code class="language-php">&lt;?php
use App\Admin\Forms\Setting;
use App\Http\Controllers\Controller;
use Dcat\Admin\Widgets\Card;
use Dcat\Admin\Layout\Content;
class UserController extends Controller
{
public function setting(Content $content)
{
return $content
-&gt;title('网站设置')
-&gt;body(new Card(new Setting()));
}
}</code></pre>
<h3>弹出确认弹窗</h3>
<p>第二个参数可忽略</p>
<pre><code class="language-php">$this-&gt;confirm('title', 'content');</code></pre>
<h3>响应方法</h3>
<p>参考 <a href="response.md">动作以及表单响应</a> 章节</p>
<h3>自定义表单保存的后续行为</h3>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Widgets\Form;
use Symfony\Component\HttpFoundation\Response;
class Setting extends Form
{
...
/**
* 设置表单保存成功后执行的JS
*
* @return string|void
*/
protected function savedScript()
{
return &lt;&lt;&lt;JS
// data 为接口返回数据
if (! data.status) {
Dcat.error(data.message);
return false;
}
Dcat.success(data.message);
if (data.redirect) {
Dcat.reload(data.redirect)
}
// 中止后续逻辑(默认逻辑)
return false;
JS;
}
/**
* 设置表单保存失败后执行的JS
*
* @return string|void
*/
protected function errorScript()
{
return &lt;&lt;&lt;JS
var errorData = JSON.parse(response.responseText);
if (errorData) {
Dcat.error(errorData.message);
} else {
console.log('提交出错', response.responseText);
}
// 终止后续逻辑执行(默认逻辑)
return false;
JS;
}
}</code></pre>
<h3>取消/启用表单的Ajax提交</h3>
<p>默认表单提交都使用Ajax进行提交,通过注入的 <a href="https://github.com/jqhph/dcat-admin/blob/2.0/resources/assets/dcat/js/extensions/Form.js">Form.js</a> 进行流程控制,如果需要原生表单行为,可以禁用此特</p>
<pre><code class="language-php">$form-&gt;ajax(false);</code></pre>
<p><a name="layout"></a></p>
<h3>布局</h3>
<p><code>column</code>多列布局</p>
<pre><code class="language-php">&lt;?php
use Dcat\Admin\Widgets\Form;
class Setting extends Form
{
public function form()
{
$this-&gt;column(6, function () {
$this-&gt;text('text1');
...
});
$this-&gt;column(6, function () {
$this-&gt;text('text2');
...
});
}
}</code></pre>
<p><code>tab</code>选项卡布局</p>
<pre><code class="language-php">&lt;?php
use Dcat\Admin\Widgets\Form;
class Setting extends Form
{
public function form()
{
$this-&gt;tab('选项卡1', function () {
$this-&gt;text('text1');
...
});
$this-&gt;tab('选项卡2', function () {
$this-&gt;text('text2');
...
});
}
}</code></pre>
<p><code>row</code>多行布局</p>
<pre><code class="language-php">public function form()
{
$this-&gt;row(function ($row) {
$row-&gt;width(3)-&gt;text('text1');
...
});
$this-&gt;row(function ($row) {
$row-&gt;width(3)-&gt;text('text2');
...
});
} </code></pre>
<p><a name="modal"></a></p>
<h3>在弹窗中显示</h3>
<h4>基本用法</h4>
<p>使用命令生成工具表单<code>php artisan admin:form ResetPassword</code>,然后修改表单文件如下</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Widgets\Form;
class ResetPassword extends Form
{
// 处理请求
public function handle(array $input)
{
$password = $input['password'] ?? null;
// 逻辑操作
return $this-&gt;response()-&gt;success('密码修改成功');
}
public function form()
{
$this-&gt;password('password')-&gt;required();
// 密码确认表单
$this-&gt;password('password_confirm')-&gt;same('password');
}
// 返回表单数据,如不需要可以删除此方法
public function default()
{
return [
'password' =&gt; '',
'password_confirm' =&gt; '',
];
}
}</code></pre>
<p>使用</p>
<pre><code class="language-php">use App\Admin\Forms\ResetPassword;
use Dcat\Admin\Widgets\Modal;
$modal = Modal::make()
-&gt;lg()
-&gt;title('修改密码')
-&gt;body(ResetPassword::make())
-&gt;button('修改密码');</code></pre>
<h4>异步加载</h4>
<p>只需要让<code>Form</code>表单类实现<code>Dcat\Admin\Contracts\LazyRenderable</code>接口即可支持异步渲染功能,修改上面创建的工具表单类如下</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Widgets\Form;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Contracts\LazyRenderable;
class ResetPassword extends Form implements LazyRenderable
{
use LazyWidget;
// 处理请求
public function handle(array $input)
{
// 获取外部传递参数
$id = $this-&gt;payload['id'] ?? null;
$password = $input['password'] ?? null;
// 逻辑操作
return $this-&gt;response()-&gt;success('密码修改成功');
}
public function form()
{
// 获取外部传递参数
$id = $this-&gt;payload['id'] ?? null;
$this-&gt;password('password')-&gt;required();
// 密码确认表单
$this-&gt;password('password_confirm')-&gt;same('password');
}
// 返回表单数据,如不需要可以删除此方法
public function default()
{
// 获取外部传递参数
$id = $this-&gt;payload['id'] ?? null;
return [
'password' =&gt; '',
'password_confirm' =&gt; '',
];
}
}</code></pre>
<p>使用代码与上面基本一致,并且我们可以用<code>payload</code>方法往表单里面传递自定义参数</p>
<pre><code class="language-php">use App\Admin\Forms\ResetPassword;
use Dcat\Admin\Widgets\Modal;
$modal = Modal::make()
-&gt;lg()
-&gt;title('修改密码')
-&gt;body(ResetPassword::make()-&gt;payload(['id' =&gt; '...'])) // 传递自定义参数
-&gt;button('修改密码');</code></pre>
<h4>表格行操作弹窗</h4>
<p>下面通过一个数据表格修改密码的行操作功能来展示弹窗结合工具表单的用法:</p>
<p>使用命令生成工具表单<code>php artisan admin:form ResetPassword</code>,然后修改表单文件如下</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Models\Administrator;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Dcat\Admin\Contracts\LazyRenderable;
class ResetPassword extends Form implements LazyRenderable
{
use LazyWidget; // 使用异步加载功能
// 处理请求
public function handle(array $input)
{
// 获取外部传递参数
$id = $this-&gt;payload['id'] ?? null;
// 表单参数
$password = $input['password'] ?? null;
if (! $id) {
return $this-&gt;response()-&gt;error('参数错误');
}
$user = Administrator::query()-&gt;find($id);
if (! $user) {
return $this-&gt;response()-&gt;error('用户不存在');
}
$user-&gt;update(['password' =&gt; bcrypt($password)]);
return $this-&gt;response()-&gt;success('密码修改成功');
}
public function form()
{
// 获取外部传递参数
//$id = $this-&gt;payload['id'] ?? null;
$this-&gt;password('password')-&gt;required();
// 密码确认表单
$this-&gt;password('password_confirm')-&gt;same('password');
}
// 返回表单数据,如不需要可以删除此方法
public function default()
{
return [
'password' =&gt; '',
'password_confirm' =&gt; '',
];
}
}</code></pre>
<p>然后运行<code>php artisan admin:action</code>命令,选择选项<code>2</code>,生成数据表格行操作类,并修改如下:</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Actions\Grid;
use App\Admin\Forms\ResetPassword as ResetPasswordForm;
use Dcat\Admin\Widgets\Modal;
use Dcat\Admin\Grid\RowAction;
class ResetPassword extends RowAction
{
protected $title = '修改密码';
public function render()
{
// 实例化表单类并传递自定义参数
$form = ResetPasswordForm::make()-&gt;payload(['id' =&gt; $this-&gt;getKey()]);
return Modal::make()
-&gt;lg()
-&gt;title($this-&gt;title)
-&gt;body($form)
-&gt;button($this-&gt;title);
}
}</code></pre>
<p>使用</p>
<pre><code class="language-php">use App\Admin\Actions\Grid\ResetPassword;
$grid-&gt;actions([new ResetPassword()]);</code></pre>
<p>效果</p>
<p><img src="{{public}}/assets/img/screenshots/modal-widget-form.png" alt="" /></p>
<p><a name="batch-modal"></a></p>
<h4>表格批量操作弹窗</h4>
<p>如果你想在批量操作按钮中使用表单弹窗,可以参考以下例子:</p>
<p>这里我们仍然沿用上面用到的<code>App\Admin\Forms\ResetPassword</code>表单,并修改如下</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Forms;
use Dcat\Admin\Models\Administrator;
use Dcat\Admin\Widgets\Form;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Contracts\LazyRenderable;
class ResetPassword extends Form implements LazyRenderable
{
use LazyWidget;
// 处理请求
public function handle(array $input)
{
// id转化为数组
$id = explode(',', $input['id'] ?? null);
$password = $input['password'] ?? null;
if (! $id) {
return $this-&gt;response()-&gt;error('参数错误');
}
$users = Administrator::query()-&gt;find($id);
if ($users-&gt;isEmpty()) {
return $this-&gt;response()-&gt;error('用户不存在');
}
// 这里改为循环批量修改
$users-&gt;each(function ($user) use ($password) {
$user-&gt;update(['password' =&gt; bcrypt($password)]);
});
return $this-&gt;response()-&gt;success('密码修改成功');
}
public function form()
{
$this-&gt;password('password')-&gt;required();
// 密码确认表单
$this-&gt;password('password_confirm')-&gt;same('password');
// 设置隐藏表单,传递用户id
$this-&gt;hidden('id')-&gt;attribute('id', 'reset-password-id');
}
// 返回表单数据,如不需要可以删除此方法
public function default()
{
return [
'password' =&gt; '',
'password_confirm' =&gt; '',
];
}
}</code></pre>
<p>然后运行<code>php artisan admin:action</code>命令,选择选项<code>1</code>,生成数据表格批量操作类,并修改如下:</p>
<pre><code class="language-php">&lt;?php
namespace App\Admin\Actions\Grid;
use App\Admin\Forms\ResetPassword as ResetPasswordForm;
use Dcat\Admin\Widgets\Modal;
use Dcat\Admin\Grid\BatchAction;
class BatchResetPassword extends BatchAction
{
protected $title = '修改密码';
public function render()
{
// 实例化表单类
$form = ResetPasswordForm::make();
return Modal::make()
-&gt;lg()
-&gt;title($this-&gt;title)
-&gt;body($form)
// 因为此处使用了表单异步加载功能,所以一定要用 onLoad 方法
// 如果是非异步方式加载表单,则需要改成 onShow 方法
-&gt;onLoad($this-&gt;getModalScript())
-&gt;button($this-&gt;title);
}
protected function getModalScript()
{
// 弹窗显示后往隐藏的id表单中写入批量选中的行ID
return &lt;&lt;&lt;JS
// 获取选中的ID数组
var key = {$this-&gt;getSelectedKeysScript()}
$('#reset-password-id').val(key);
JS;
}
}</code></pre>
<p>使用</p>
<pre><code class="language-php">use App\Admin\Actions\Grid\BatchResetPassword;
$grid-&gt;batchActions([new BatchResetPassword()]);</code></pre>