表单字段的使用

model-form中内置了大量的form组件来帮助你快速的构建form表单

公共方法

设置表单值 (value)

  1. $form->text('title')->value('text...');

设置默认值 (default)

  1. $form->text('title')->default('text...');

此方法仅在新增页面有效,如果编辑页面也需要设置默认值,可以参考以下方法

  1. $form->text('xxx')->default('默认值', true);

设置提示信息 (help)

  1. $form->text('title')->help('help...');

设置属性 (attribute)

  1. $form->text('title')->attribute(['data-title' => 'title...']);
  2. $form->text('title')->attribute('data-title', 'title...');

设置为必填 (required)

  1. $form->text('title')->required();
  2. // 不显示"*"号
  3. $form->text('title')->required(false);

设置为不可编辑 (disable)

  1. $form->text('title')->disable();

设置占位符 (placeholder)

  1. $form->text('title')->placeholder('请输入。。。');

设置宽度 (width)

  1. $form->text('title')->width(8, 2);

设置验证规则 (rules)

具体使用可参考表单验证

修改待保存的表单输入值 (saving)

通过saving方法可以更改待保存数据的格式。

  1. use Dcat\Admin\Support\Helper;
  2. $form->multipleFile('files')->saving(function ($paths) {
  3. $paths = Helper::array($paths);
  4. // 获取数据库当前行的其他字段
  5. $username = $this->username;
  6. // 最终转化为json保存到数据库
  7. return json_encode($paths);
  8. });

修改表单数据显示 (customFormat)

通过customFormat方法可以改变从外部注入到表单的字段值。

如下例子中,multipleFile字段要求待渲染的字段值为数组格式,我们可以通过customFormat方法把从数据库查出的字段值转化为array格式

  1. use Dcat\Admin\Support\Helper;
  2. $form->multipleFile('files')->saving(function ($paths) {
  3. $paths = Helper::array($paths);
  4. return json_encode($paths);
  5. })->customFormat(function ($paths) {
  6. // 获取数据库当前行的其他字段
  7. $username = $this->username;
  8. // 转为数组
  9. return Helper::array($paths);
  10. });

在弹窗中隐藏

如果不想在弹窗中显示某个字段,可以使用Form\Field::hideInDialog方法

  1. $form->display('id');
  2. $form->text('title');
  3. $form->textarea('contents')->hideInDialog();

保存为字符串类型 saveAsString

saveAsString方法可以把表单值转化为string类型保存,当保存的数据库字段值不允许为null时非常有用;

  1. $form->text('nickname')->saveAsString();

保存为json类型 saveAsJson

saveAsJson可以把表单值保存为json格式

  1. $form->text('nickname')->saveAsJson();

文本 (text)

  1. $form->text($column, [$label]);
  2. // 添加提交验证规则
  3. $form->text($column, [$label])->rules('required|min:10');

隐藏字段 (hidden)

通过hidden方法可以给你的表单设置一个隐藏字段。

  1. $form->hidden('author_id')->value(Admin::user()->getKey());

通常可以结合saving事件使用

  1. $form->hidden('author_id');
  2. $form->saving(function (Form $form) {
  3. $form->author_id = Admin::user()->getKey();
  4. });

下拉选框单选 (select)

  1. $form->select($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);

或者从api中获取选项列表:

  1. $form->select($column[, $label])->options('/api/users');
  2. // 使用ajax并显示所选项目
  3. $form->select($column[, $label])->options(Model::class)->ajax('/api/users');
  4. // 或指定名称和ID
  5. $form->select($column[, $label])->options(Model::class, 'name', 'id')->ajax('/api/users');

其中api接口的格式必须为下面格式:

  1. [
  2. {
  3. "id": 9,
  4. "text": "xxx"
  5. },
  6. {
  7. "id": 21,
  8. "text": "xxx"
  9. },
  10. ...
  11. ]

如果选项过多,可通过ajax方式动态分页载入选项:

  1. $form->select('user_id')->options(function ($id) {
  2. $user = User::find($id);
  3. if ($user) {
  4. return [$user->id => $user->name];
  5. }
  6. })->ajax('api/users');

使用model方法在編輯時載入資料:

  1. $form->select('user_id')->model(User::class, 'id', 'name');

上面的代碼跟下面這個是一樣的

  1. $form->select('user_id')->options(function ($id) {
  2. $user = User::find($id);
  3. if ($user) {
  4. return [$user->id => $user->name];
  5. }
  6. });

API /admin/api/users接口的代码:

  1. public function users(Request $request)
  2. {
  3. $q = $request->get('q');
  4. return User::where('name', 'like', "%$q%")->paginate(null, ['id', 'name as text']);
  5. }

接口返回的数据结构为

  1. {
  2. "total": 4,
  3. "per_page": 15,
  4. "current_page": 1,
  5. "last_page": 1,
  6. "next_page_url": null,
  7. "prev_page_url": null,
  8. "from": 1,
  9. "to": 3,
  10. "data": [
  11. {
  12. "id": 9,
  13. "text": "xxx"
  14. },
  15. {
  16. "id": 21,
  17. "text": "xxx"
  18. },
  19. {
  20. "id": 42,
  21. "text": "xxx"
  22. },
  23. {
  24. "id": 48,
  25. "text": "xxx"
  26. }
  27. ]
  28. }

下拉选框联动 (load)

select组件支持父子关系的单向联动:

  1. $form->select('province')->options(...)->load('city', '/api/city');
  2. $form->select('city');

其中load('city', '/api/city');的意思是,在当前select的选项切换之后,会把当前选项的值通过参数q, 调用接口/api/city,并把api返回的数据填充为city选择框的选项,其中api/api/city返回的数据格式必须符合:

  1. [
  2. {
  3. "id": 9,
  4. "text": "xxx"
  5. },
  6. {
  7. "id": 21,
  8. "text": "xxx"
  9. },
  10. ...
  11. ]

控制器action的代码示例如下:

  1. public function city(Request $request)
  2. {
  3. $provinceId = $request->get('q');
  4. return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);
  5. }

selectTablemultipleSelectTableradiocheckbox也可以使用load方法联动selectmultipleSelect表单,用法和上面的示例一致。

联动多个字段 (loads)

使用loads方法可以联动多个字段,用法如下

  1. $form->select('status')
  2. ->options(...)
  3. ->loads(['field1', 'field2'], ['/api/field1', '/api/field2']);
  4. $form->select('field1');
  5. $form->select('field2');

api返回的数据格式与load方法一致,selectTablemultipleSelectTableradiocheckbox也可以使用loads方法联动。

下拉选框多选 (multipleSelect)

{tip} 注入这个字段的数据(从数据库查出来的)可以是一个以,隔开的字符串,也可以是json字符串或array数组。

  1. $form->multipleSelect($column[, $label])
  2. ->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])
  3. ->saving(function ($value) {
  4. // 转化成json字符串保存到数据库
  5. return json_encode($value);
  6. });
  7. // 使用ajax并显示所选项目:
  8. $form->multipleSelect($column[, $label])->options(Model::class)->ajax('ajax_url');
  9. // 或指定名称和ID
  10. $form->multipleSelect($column[, $label])->options(Model::class, 'name', 'id')->ajax('ajax_url');

多选框可以处理两种情况,第一种是ManyToMany的关系。

  1. class Post extends Models
  2. {
  3. public function tags()
  4. {
  5. return $this->belongsToMany(Tag::class);
  6. }
  7. }
  8. return Form::make(Post::with('tags'), function (Form $form) {
  9. ...
  10. $form->multipleSelect('tags')
  11. ->options(Tag::all()->pluck('name', 'id'))
  12. ->customFormat(function ($v) {
  13. if (! $v) {
  14. return [];
  15. }
  16. // 从数据库中查出的二维数组中转化成ID
  17. return array_column($v, 'id');
  18. });
  19. });

第二种是将选项数组存储到单字段中,如果字段是字符串类型,那就需要在模型里面为该字段定义访问器和修改器来存储和读取了。

如果选项过多,可通过ajax方式动态分页载入选项:

  1. $form->select('friends')->options(function ($ids) {
  2. return User::find($ids)->pluck('name', 'id');
  3. })->ajax('api/users');

API /admin/api/users接口的代码:

  1. public function users(Request $request)
  2. {
  3. $q = $request->get('q');
  4. return User::where('name', 'like', "%$q%")->paginate(null, ['id', 'name as text']);
  5. }

接口返回的数据结构为

  1. {
  2. "total": 4,
  3. "per_page": 15,
  4. "current_page": 1,
  5. "last_page": 1,
  6. "next_page_url": null,
  7. "prev_page_url": null,
  8. "from": 1,
  9. "to": 3,
  10. "data": [
  11. {
  12. "id": 9,
  13. "text": "xxx"
  14. },
  15. {
  16. "id": 21,
  17. "text": "xxx"
  18. },
  19. {
  20. "id": 42,
  21. "text": "xxx"
  22. },
  23. {
  24. "id": 48,
  25. "text": "xxx"
  26. }
  27. ]
  28. }

表格选择器 (selectTable)

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Models\Administrator;
  3. $form->selectTable($field)
  4. ->title('弹窗标题')
  5. ->dialogWidth('50%') // 弹窗宽度,默认 800px
  6. ->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
  7. ->model(Administrator::class, 'id', 'name'); // 设置编辑数据显示
  8. // 上面的代码等同于
  9. $form->selectTable($field)
  10. ->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
  11. ->options(function ($v) { // 设置编辑数据显示
  12. if (! $v) {
  13. return [];
  14. }
  15. return Administrator::find($v)->pluck('name', 'id');
  16. });

定义渲染类如下,需要继承Dcat\Admin\Grid\LazyRenderable

{tip} 这里使用了数据表格异步加载功能,详细用法请参考异步加载

  1. <?php
  2. namespace App\Admin\Renderable;
  3. use Dcat\Admin\Grid;
  4. use Dcat\Admin\Grid\LazyRenderable;
  5. use Dcat\Admin\Models\Administrator;
  6. class UserTable extends LazyRenderable
  7. {
  8. public function grid(): Grid
  9. {
  10. // 获取外部传递的参数
  11. $id = $this->id;
  12. return Grid::make(Administrator::where('xxx_id', $id), function (Grid $grid) {
  13. $grid->column('id');
  14. $grid->column('username');
  15. $grid->column('name');
  16. $grid->column('created_at');
  17. $grid->column('updated_at');
  18. $grid->quickSearch(['id', 'username', 'name']);
  19. $grid->paginate(10);
  20. $grid->disableActions();
  21. $grid->filter(function (Grid\Filter $filter) {
  22. $filter->like('username')->width(4);
  23. $filter->like('name')->width(4);
  24. });
  25. });
  26. }
  27. }

效果

表单字段的使用 - 图1

设置选中后将保存到表单的字段和显示的字段

  1. $form->selectTable($field)
  2. ->from(UserTable::make(['id' => $form->getKey()]))
  3. ->options(function ($v) { // 设置编辑数据显示
  4. if (! $v) {
  5. return [];
  6. }
  7. return Administrator::find($v)->pluck('name', 'id');
  8. })
  9. ->pluck('name', 'id'); // 第一个参数为显示的字段,第二个参数为选中后将保存到表单的字段
  10. // 上面的代码也可以简化为
  11. $form->selectTable($field)
  12. ->from(UserTable::make(['id' => $form->getKey()]))
  13. ->model(Administrator::class, 'id', 'name'); // 设置编辑数据显示

多选 (multipleSelectTable)

多选的用法与上述selectTable方法一致

  1. $form->multipleSelectTable($field)
  2. ->max(10) // 最多选择 10 个选项,不传则不限制
  3. ->from(UserTable::make(['id' => $form->getKey()])) // 设置渲染类实例,并传递自定义参数
  4. ->model(Administrator::class, 'id', 'name') // 设置编辑数据显示
  5. ->saving(function ($v) {
  6. // $v 是表单提交的字段值,默认是数组类型,这里需要手动转换一下
  7. // 保存为以 "," 隔开的字符串,如果是多对多关联关系,则不需要转换。
  8. return implode(',', $v);
  9. });

多选盒 (listbox)

使用方法和multipleSelect类似。

{tip} 注入这个字段的数据(从数据库查出来的)可以是一个以,隔开的字符串,也可以是json字符串或array数组。

  1. $form->listbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);

长文本 (textarea)

  1. $form->textarea($column[, $label])->rows(10);

单选 (radio)

  1. $form->radio($column[, $label])->options(['m' => 'Female', 'f'=> 'Male'])->default('m');

多选 (checkbox)

options()方法用来设置选择项:

  1. $form->checkbox($column[, $label])
  2. ->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])
  3. ->saving(function ($value) {
  4. // 转化成json字符串保存到数据库
  5. return json_encode($value);
  6. });

启用选中全部功能

  1. $form->checkbox('column')->canCheckAll();

autocomplete

此表单可以在填写表单时进行对表单值进行搜索,并把结果展示在下拉列表中,用法如下

  1. $form->autocomplete($column[, $label])->options(['foo', 'bar', ...]);
  2. // 设置分组名称
  3. $form->autocomplete($column[, $label])->groups([
  4. [
  5. 'label' => 'group name',
  6. 'options' => ['foo', 'bar', ...],
  7. ],
  8. ]);

效果如下 表单字段的使用 - 图2

从远程API获取数据

也可以从远程API中获取数据

  1. // ajax 函数的第一个参数为 ajax url, 第二个参数为 valueField(可选), 第三个参数为 groupField(可选)
  2. $form->autocomplete($column[, $label])->ajax('/countries', 'name', 'region');

远程API 服务端的请求参数为query,示例代码如下:

  1. class CountryController extends AdminController
  2. {
  3. public function search()
  4. {
  5. $countries = Country::when(request('query'), function ($query, $value) {
  6. $query->where('name', 'like', "%{$value}%");
  7. })->get();
  8. return Admin::json($countries->toArray());
  9. }
  10. }

自定义 autocomplete 的设置:

详细设置请参考: devbridge/jQuery-Autocomplete

  1. $js = <<<JS
  2. function (suggestion) {
  3. alert('You selected: ' + suggestion.value + ', ' + suggestion.data);
  4. }
  5. JS;
  6. $form->autocomplete($column[, $label])->configs([
  7. 'minChars' => 5,
  8. 'noCache' => true,
  9. 'onSelect' => JavaScript::make($js),
  10. ]);

configs 同样也支持闭包:

  1. $form->autocomplete($column[, $label])->configs(function($model, $value){
  2. return [
  3. ....
  4. ];
  5. });

表单联动

autocomplete 的联动逻辑和select的刚好相反。 depends 需要写在受影响的字段,不限上级字段类型,上级字段的值将同时上传到API。

  1. $form->select('region')->options([
  2. 'asia',
  3. 'Africa',
  4. 'America',
  5. 'Europe',
  6. ]);
  7. $form->autocomplete('country')->ajax('/countries', 'name', 'region');
  8. // 将会发出 /states?query={query}&region={region}&country={country} 的请求
  9. $form->autocomplete('addr')->ajax('/states', 'name')->depends(['region', 'country']);

邮箱 (email)

  1. $form->email($column[, $label]);

密码 (password)

  1. $form->password($column[, $label]);

链接 (url)

  1. $form->url($column[, $label]);

IP地址 (ip)

  1. $form->ip($column[, $label]);

手机 (mobile)

  1. $form->mobile($column[, $label])->options(['mask' => '999 9999 9999']);

颜色选择器 (color)

  1. $form->color($column[, $label]);

时间 (time)

  1. $form->time($column[, $label]);
  2. // 设置时间格式,更多格式参考http://momentjs.com/docs/#/displaying/format/
  3. $form->time($column[, $label])->format('HH:mm:ss');

日期 (date)

  1. $form->date($column[, $label]);
  2. // 设置日期格式,更多格式参考http://momentjs.com/docs/#/displaying/format/
  3. $form->date($column[, $label])->format('YYYY-MM-DD');

时间日期 (datetime)

  1. $form->datetime($column[, $label]);
  2. // 设置日期格式,更多格式参考http://momentjs.com/docs/#/displaying/format/
  3. $form->datetime($column[, $label])->format('YYYY-MM-DD HH:mm:ss');

时间范围 (timeRange)

$startTime$endTime为开始和结束时间字段:

  1. $form->timeRange($startTime, $endTime, 'Time Range');

日期范围 (dateRange)

$startDate$endDate为开始和结束日期字段:

  1. $form->dateRange($startDate, $endDate, 'Date Range');

时间日期范围 (datetimeRange)

$startDateTime$endDateTime为开始和结束时间日期:

  1. $form->datetimeRange($startDateTime, $endDateTime, 'DateTime Range');

范围 (range)

  1. $form->range('start_column', 'end_column', '范围');

文件上传 (file)

使用文件上传功能之前需要先完成上传配置。文件上传配置以及内置方法请参考:图片/文件上传.

文件上传目录在文件config/admin.php中的upload.file中配置,如果目录不存在,需要创建该目录并开放写权限。

{tip} 文件或图片上传表单字段请不要在模型中设置访问器修改器拼接域名,如有相关需求可参考文件/图片域名拼接

  1. $form->file($column[, $label]);
  2. // 修改文件上传路径和文件名
  3. $form->file($column[, $label])->move($dir, $name);
  4. // 并设置上传文件类型
  5. $form->file($column[, $label])->rules('mimes:doc,docx,xlsx');
  6. // 添加文件删除按钮
  7. $form->file($column[, $label])->removable();

图片上传 (image)

使用图片上传功能之前需要先完成上传配置。图片上传配置以及内置方法请参考:图片/文件上传.

图片上传目录在文件config/admin.php中的upload.image中配置,如果目录不存在,需要创建该目录并开放写权限。

可以使用压缩、裁切、添加水印等各种方法,需要先安装intervention/image

更多使用方法请参考[Intervention]:

{tip} 文件或图片上传表单字段请不要在模型中设置访问器修改器拼接域名,如有相关需求可参考文件/图片域名拼接

  1. $form->image($column[, $label]);
  2. // 修改图片上传路径和文件名
  3. $form->image($column[, $label])->move($dir, $name);
  4. // 剪裁图片
  5. $form->image($column[, $label])->crop(int $width, int $height, [int $x, int $y]);
  6. // 加水印
  7. $form->image($column[, $label])->insert($watermark, 'center');

多图和多文件上传 (multipleImage/multipleFile)

多图片上传表单继承自单图上传表单,多文件上传表单继承自单文件上传表单。

{tip} 注入这个字段的数据(从数据库查出来的)可以是一个以,隔开的字符串,也可以是json字符串或array数组。

  1. // 多图
  2. $form->multipleImage($column[, $label]);
  3. // 限制最大上传数量
  4. $form->multipleImage($column[, $label])->limit(3);
  5. // 多文件
  6. $form->multipleFile($column[, $label]);
  7. // 限制最大上传数量
  8. $form->multipleFile($column[, $label])->limit(5);

多图/文件上传的时候提交的数据是一个array数组,你可以通过以下方式把数据在保存进数据库之前改为你想要的格式:

  1. // 转化为json格式保存到数据库
  2. $form->multipleFile($column[, $label])->saving(function ($paths) {
  3. // 可以转化为由 , 隔开的字符串格式
  4. // return implode(',', $paths);
  5. // 也可以转化为json
  6. return json_encode($paths);
  7. });

当然,如果你想保存为其他任意格式都是可以的,只是如果要保存其他格式,需要通过用customFormat方法把数据转化为一维数组展示,如:

  1. $form->multipleFile($column[, $label])
  2. ->customFormat(function ($paths) {
  3. return collect($paths)->map(function ($value) {
  4. return explode('|', $value);
  5. })->flatten()->toArray();
  6. })
  7. ->saving(function ($paths) {
  8. return implode('|', $paths);
  9. });

启用可排序功能

  1. $form->multipleImage('images')->sortable();

富文本编辑器 (editor)

系统集成了TinyMCE编辑器作为内置编辑器。

基本使用

  1. $form->editor($column[, $label]);

设置语言包

默认支持简体中文和英文两种语言,如需其他语言可以通过以下方式设置语言包地址。

  1. $form->editor('content')->languageUrl(url('TinyMCE/langs/de.js'));

编辑器配置

具体配置等的使用可以参考官方文档中文文档

  1. <?php
  2. use Dcat\Admin\Support\JavaScript;
  3. $form->editor('content')->options([
  4. 'toolbar' => [],
  5. 'setup' => JavaScript::make(
  6. <<<JS
  7. function (editor) {
  8. console.log('编辑器初始化成功', editor)
  9. }
  10. JS
  11. ),
  12. ]);

设置高度

默认值为400

  1. $form->editor('content')->height('600');

只读

  1. $form->editor('content')->readOnly();
  2. // 或
  3. $form->editor('content')->disable();

图片上传

设置图片上传disk配置,默认上传到admin.upload.disk指定的配置

  1. // 上传到oss
  2. $form->editor('content')->disk('oss');

设置图片上传目录,默认为tinymce/images

  1. $form->editor('content')->imageDirectory('editor/images');

自定义上传接口,接口返回格式需要是{"location": "图片url"}

  1. $form->editor('content')->imageUrl('editor/upload-image');

全局设置

如果你需要对编辑器进行全局设置,可以在app\Admin\bootstrap.php加上以下代码

  1. <?php
  2. use Dcat\Admin\Form\Field\Editor;
  3. Editor::resolving(function (Editor $editor) {
  4. // 设置默认配置
  5. $editor->options([...]);
  6. // 设置编辑器图片默认上传到七牛云
  7. $editor->disk('qiniu');
  8. });

Markdown编辑器 (markdown)

系统集成了editor-md编辑器作为内置Markdown编辑器。

基本使用

  1. $form->markdown($column[, $label]);

设置语言包

默认支持简体中文和英文两种语言,如需其他语言可以通过以下方式设置语言包地址。

  1. $form->markdown('content')->languageUrl(admin_asset('@admin/dcat/plugins/editor-md/languages/zh-tw.js'));

编辑器配置

具体配置等的使用可以参考官方文档

  1. <?php
  2. use Dcat\Admin\Support\JavaScript;
  3. $form->markdown('content')->options([
  4. 'onpreviewing' => JavaScript::make(
  5. <<<JS
  6. function() {
  7. // console.log("onpreviewing =>", this, this.id, this.settings);
  8. // on previewing you can custom css .editormd-preview-active
  9. }
  10. JS
  11. ),
  12. ]);

设置高度

默认值为500

  1. $form->markdown('content')->height('600');

只读

  1. $form->markdown('content')->readOnly();
  2. // 或
  3. $form->markdown('content')->disable();

图片上传

设置图片上传disk配置,默认上传到admin.upload.disk指定的配置

  1. // 上传到oss
  2. $form->markdown('content')->disk('oss');

设置图片上传目录,默认为markdown/images

  1. $form->markdown('content')->imageDirectory('markdown/images');

自定义上传接口,接口返回格式需要是{"success": 1, "url": "图片url"}

  1. $form->markdown('content')->imageUrl('markdown/upload-image');

全局设置

如果你需要对编辑器进行全局设置,可以在app\Admin\bootstrap.php加上以下代码

  1. <?php
  2. use Dcat\Admin\Form\Field\Markdown;
  3. Markdown::resolving(function (Markdown $markdown) {
  4. // 设置默认配置
  5. $markdown->options([...]);
  6. // 设置编辑器图片默认上传到七牛云
  7. $markdown->disk('qiniu');
  8. });

开关 (switch)

使用

  1. $form->switch($column[, $label]);

开关表单保存到数据库的默认值为10,如果需要更改保存到数据库的值,可以这样使用

  1. $form->switch($column[, $label])
  2. ->customFormat(function ($v) {
  3. return $v == '打开' ? 1 : 0;
  4. })
  5. ->saving(function ($v) {
  6. return $v ? '打开' : '关闭';
  7. });

地图 (map)

地图控件,用来选择经纬度,$latitude, $longitude为经纬度字段。

使用这个功能需要在 config/admin.php 文件中修改 map_provider 的值(目前支持的地图为:”tencent”, “google”, “yandex”,不同地图需要自己申请相应的 KEY 并在 .env 文件中配置,然后需要在app/Admin/bootstrap.php中加入以下代码

  1. Form\Field\Map::requireAssets();

使用

  1. $form->map($latitude, $longitude, $label);

滑动条 (slider)

可以用来数字类型字段的选择,比如年龄:

  1. $form->slider($column[, $label])->options(['max' => 100, 'min' => 1, 'step' => 1, 'postfix' => 'years old']);

更多options请参考:https://github.com/IonDen/ion.rangeSlider#settings

仅显示 (display)

只显示字段,不做任何操作:

  1. $form->display($column[, $label]);
  2. //更复杂的显示
  3. $form->display($column[, $label])->with(function ($value) {
  4. return "<img src="$value" />";
  5. });

单位符号 (currency)

  1. $form->currency($column[, $label]);
  2. // 设置单位符号
  3. $form->currency($column[, $label])->symbol('¥');

数字 (number)

  1. $form->number($column[, $label]);

费率 (rate)

  1. $form->rate($column[, $label]);

分割线 (divider)

  1. $form->divider();

自定义内容 (html)

插入html内容,参数可以是实现了HtmlableRenderable或者实现了__toString()方法的类

  1. $form->html('你的html内容', $label = '');

标签 (tags)

插入逗号(,)隔开的字符串tags

  1. $form->tags('keywords');

tags同样支持ManyToMany的关系,示例如下:

  1. $form->tags('tags', '文章标签')
  2. ->pluck('name', 'id') // name 为需要显示的 Tag 模型的字段,id 为主键
  3. ->options(Tag::all());// 下拉框选项

注意:处理ManyToMany关系时必须调用pluck方法,指定显示的字段名和主键。 此外 options 方法传入一个Collection对象时,options会自动调用该对象的pluck方法转为['主键名' => '显示字段名'] 数组,作为下拉框选项。或者可以直接使用['主键名' => '显示字段名']这样的数组作为参数。

tags还支持saving方法用于处理提交的数据,示例如下:

  1. $form->tags('tags', '文章标签')
  2. ->pluck('name', 'id')
  3. ->options(Tag::all())
  4. ->saving(function ($value) {
  5. return $value;
  6. });

saving 方法接收一个「参数为 tags 的提交值,返回值为修改后的 tags 提交值」的闭包,可以用于实现自动创建新 tag 或其它功能。

如果选项过多,可通过ajax方式动态分页载入选项:

  1. $form->tags('friends')->options(function ($ids) {
  2. return User::find((array) $ids)->pluck('name', 'id');
  3. })->ajax('api/users');

API /admin/api/users接口的代码:

  1. public function users(Request $request)
  2. {
  3. $q = $request->get('q');
  4. return User::where('name', 'like', "%$q%")->paginate(null, ['id', 'name as text']);
  5. }

接口返回的数据结构为

  1. {
  2. "total": 4,
  3. "per_page": 15,
  4. "current_page": 1,
  5. "last_page": 1,
  6. "next_page_url": null,
  7. "prev_page_url": null,
  8. "from": 1,
  9. "to": 3,
  10. "data": [
  11. {
  12. "id": 9,
  13. "text": "xxx"
  14. },
  15. {
  16. "id": 21,
  17. "text": "xxx"
  18. },
  19. {
  20. "id": 42,
  21. "text": "xxx"
  22. },
  23. {
  24. "id": 48,
  25. "text": "xxx"
  26. }
  27. ]
  28. }

图标选择器 (icon)

选择font-awesome图标

  1. $form->icon('icon');

树形选择器 (tree)

树形结构表单

  1. $form->tree('permissions')
  2. ->nodes(Model::get()->toArray()) // 设置所有节点
  3. ->customFormat(function ($v) { // 格式化外部注入的值
  4. if (!$v) return [];
  5. return array_column($v, 'id');
  6. });
  7. // 修改节点的字段名称
  8. // 默认 “id” “name” “parent_id”
  9. $form->tree('permissions')
  10. ->nodes($permissionModel->allNodes())
  11. ->setIdColumn('id')
  12. ->setTitleColumn('title')
  13. ->setParentColumn('parent');
  14. // 默认是不保存父节点的值的,因为一般来说父节点只是作为标题的形式存在
  15. // 禁止过滤父节点的值
  16. $form->tree('permissions')
  17. ->nodes($permissionModel->allNodes())
  18. ->exceptParentNode(false);
  19. // 默认收缩子节点
  20. $form->tree('permissions')
  21. ->nodes($permissionModel->allNodes())
  22. ->expand(false);

tree表单默认不允许单独选中父节点,可以通过treeState(false)开启这个功能

  1. $form->tree('xxx')
  2. ->treeState(false) # 允许单独选择父节点
  3. ->setTitleColumn('title')
  4. ->nodes(...);

效果

表单字段的使用 - 图3

表格表单 (table)

如果某一个字段存储的是json格式的二维数组,可以使用table表单组件来实现快速的编辑:

  1. $form->table('extra', function (NestedForm $table) {
  2. $table->text('key');
  3. $table->text('value');
  4. $table->text('desc');
  5. });

同时在模型里面给这个字段增加访问器和修改器:

  1. public function getExtraAttribute($extra)
  2. {
  3. return array_values(json_decode($extra, true) ?: []);
  4. }
  5. public function setExtraAttribute($extra)
  6. {
  7. $this->attributes['extra'] = json_encode(array_values($extra));
  8. }

这个组件类似于hasMany组件,不过是用来处理单个字段的情况,适用于简单的二维数据。

一对多 (hasMany)

一对多内嵌表格,用于处理一对多的关系,下面是个简单的例子:

有两张表是一对多关系:

  1. CREATE TABLE `demo_painters` (
  2. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  3. `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  4. `bio` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  5. `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  6. `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  7. PRIMARY KEY (`id`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
  9. CREATE TABLE `demo_paintings` (
  10. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  11. `painter_id` int(10) unsigned NOT NULL,
  12. `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  13. `body` text COLLATE utf8_unicode_ci NOT NULL,
  14. `completed_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  15. `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  16. `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  17. PRIMARY KEY (`id`),
  18. KEY painter_id (`painter_id`)
  19. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

表的模型为:

  1. <?php
  2. namespace App\Models\Demo;
  3. use Illuminate\Database\Eloquent\Model;
  4. class Painter extends Model
  5. {
  6. public function paintings()
  7. {
  8. return $this->hasMany(Painting::class, 'painter_id');
  9. }
  10. }
  1. <?php
  2. namespace App\Models\Demo;
  3. use Illuminate\Database\Eloquent\Model;
  4. class Painting extends Model
  5. {
  6. protected $fillable = ['title', 'body', 'completed_at'];
  7. public function painter()
  8. {
  9. return $this->belongsTo(Painter::class, 'painter_id');
  10. }
  11. }

构建表单代码如下:

  1. use App\Models\Demo\Painter;
  2. // 这里需要显式地指定关联关系
  3. $builder = Painter::with('paintings');
  4. // 如果你使用的是数据仓库,则可以这样指定关联关系
  5. // $repository = new Painter(['paintings']);
  6. return Form::make($builder, function (Form $form) {
  7. $form->display('id', 'ID');
  8. $form->text('username')->rules('required');
  9. $form->textarea('bio')->rules('required');
  10. $form->hasMany('paintings', function (Form\NestedForm $form) {
  11. $form->text('title');
  12. $form->textarea('body');
  13. $form->datetime('completed_at');
  14. });
  15. $form->display('created_at', 'Created At');
  16. $form->display('updated_at', 'Updated At');
  17. // 也可以设置label
  18. // $form->hasMany('paintings', '画作', function (Form\NestedForm $form) {
  19. // ...
  20. // });
  21. });

效果

表单字段的使用 - 图4

表格模式 (table)

如果你想要显示表格模式,可以这样使用

  1. use Dcat\Admin\Support\Helper;
  2. $form->hasMany('paintings', function (Form\NestedForm $form) {
  3. ...
  4. })->useTable();

效果

表单字段的使用 - 图5

内嵌 (embeds)

{tip} 内嵌表单不支持图片和文件上传表单。

用于处理mysqlJSON类型字段数据或者mongodbobject类型数据,也可以将多个field的数据值以JSON字符串的形式存储在mysql的字符串类型字段中

比如orders表中的JSON或字符串类型的extra字段,用来存储多个field的数据,先定义model:

  1. class Order extends Model
  2. {
  3. protected $casts = [
  4. 'extra' => 'json',
  5. ];
  6. }

然后在form中使用:

  1. $form->embeds('extra', function ($form) {
  2. $form->text('extra1')->rules('required');
  3. $form->email('extra2')->rules('required');
  4. $form->mobile('extra3');
  5. $form->datetime('extra4');
  6. $form->dateRange('extra5', 'extra6', '范围')->rules('required');
  7. });
  8. // 自定义标题
  9. $form->embeds('extra', '附加信息', function ($form) {
  10. ...
  11. });

回调函数里面构建表单元素的方法调用和外面是一样的。