Dcat\Admin自定义form组件
以实现对json字段的key进行select封装SelectKeyValue组件
{"age": "11", "name": "张三", "height": "175"}
实现效果
继承Dcat\Admin\Form\Field, 实现文件 app\ExtField\SelectKeyValue.php
<?php
namespace App\ExtField;
use Dcat\Admin\Admin;
use Dcat\Admin\Form\Field;
use Dcat\Admin\Support\Helper;
use Illuminate\Support\Arr;
class SelectKeyValue extends Field
{
// 自定义视图文件 resources\views\selectkeyvalue.blade.php
protected $view = 'selectkeyvalue';
const DEFAULT_FLAG_NAME = '_def_';
/**
* Fill data to the field.
*
* @param array $data
*
* @return array
*/
public function formatFieldData($data)
{
$this->data = $data;
return Helper::array(Arr::get($data, $this->normalizeColumn(), $this->value));
}
public function options($options = [])
{
if ($options instanceof \Closure) {
$this->options = $options;
return $this;
}
// remote options
if (is_string($options)) {
// reload selected
if (class_exists($options) && in_array(Model::class, class_parents($options))) {
return $this->model(...func_get_args());
}
return $this->loadRemoteOptions(...func_get_args());
}
$this->options = Helper::array($options);
return $this;
}
/**
* {@inheritdoc}
*/
public function getValidator(array $input)
{
if ($this->validator) {
return $this->validator->call($this, $input);
}
if (!is_string($this->column)) {
return false;
}
$rules = $attributes = [];
if (!$fieldRules = $this->getRules()) {
return false;
}
if (!Arr::has($input, $this->column)) {
return false;
}
$rules["{$this->column}.keys.*"] = 'distinct';
$rules["{$this->column}.values.*"] = $fieldRules;
$attributes["{$this->column}.keys.*"] = __('Key');
$attributes["{$this->column}.values.*"] = __('Value');
$input = $this->prepareValidatorInput($input);
return validator($input, $rules, $this->getValidationMessages(), $attributes);
}
protected function prepareValidatorInput(array $input)
{
Arr::forget($input, $this->column . '.' . static::DEFAULT_FLAG_NAME);
return $input;
}
protected function addScript()
{
$value = old($this->column, $this->value());
$number = $value ? count($value) : 0;
$class = $this->getElementClassString();
$this->script = <<<JS
(function () {
var index = {$number};
$('.{$class}-add').on('click', function () {
var tpl = $('template.{$class}-tpl').html().replace('{key}', index).replace('{key}', index);
$('tbody.kv-{$class}-table').append(tpl);
index++;
});
$('tbody').on('click', '.{$class}-remove', function () {
$(this).closest('tr').remove();
});
})();
JS;
}
protected function prepareInputValue($value)
{
unset($value[static::DEFAULT_FLAG_NAME]);
if (empty($value)) {
return '[]';
}
return json_encode(array_combine($value['keys'], $value['values']));
}
// 主要是实现render()方法
public function render()
{
$this->addScript();
$this->addVariables([
'options' => $this->options,
]);
Admin::style('td .form-group {margin-bottom: 0 !important;}');
return parent::render();
}
}
视图文件 resources\views\selectkeyvalue.blade.php
<div class="{{ $viewClass['form-group'] }}">
<label class="{{ $viewClass['label'] }} control-label">{{ $label }}</label>
<div class="{{ $viewClass['field'] }}">
<span name="{{ $name }}"></span>
<input name="{{ $name }}[{{ \Dcat\Admin\Form\Field\KeyValue::DEFAULT_FLAG_NAME }}]" type="hidden" />
<div class="help-block with-errors"></div>
<table class="table table-hover">
<thead>
<tr>
<th>{{ __('Key') }}</th>
<th>{{ __('Value') }}</th>
<th style="width: 85px;"></th>
</tr>
</thead>
<tbody class="kv-{{ $class }}-table">
@foreach (old("{$column}.keys", $value ?: []) as $k => $v)
@php($keysErrorKey = "{$column}.keys.{$loop->index}")
@php($valsErrorKey = "{$column}.values.{$loop->index}")
<tr>
<td>
<div class="form-group {{ $errors->has($keysErrorKey) ? 'has-error' : '' }}">
<div class="col-sm-12">
<div class="help-block with-errors"></div>
@if ($errors->has($keysErrorKey))
@foreach ($errors->get($keysErrorKey) as $message)
<label class="control-label" for="inputError"><i
class="feather icon-x-circle"></i>
{{ $message }}</label><br />
@endforeach
@endif
{{-- 默认键展示 --}}
@if ($options)
<div class="{{ $viewClass['field'] }}">
<select class="form-control {{ $class }}" style="width: 100%;"
name="{{ $name }}[keys][{{ $loop->index }}]"
{!! $attributes !!}>
<option value=""></option>
@foreach ($options as $select => $option)
<option value="{{ $select }}"
{{ Dcat\Admin\Support\Helper::equal($select, old("{$column}.keys.{$k}", $k)) ? 'selected' : '' }}>
{{ $option }}</option>
@endforeach
</select>
</div>
@else
<input name="{{ $name }}[keys][{{ $loop->index }}]"
value="{{ old("{$column}.keys.{$k}", $k) }}" class="form-control"
required />
@endif
</div>
</div>
</td>
<td>
<div class="form-group {{ $errors->has($valsErrorKey) ? 'has-error' : '' }}">
<div class="col-sm-12">
<div class="help-block with-errors"></div>
@if ($errors->has($valsErrorKey))
@foreach ($errors->get($valsErrorKey) as $message)
<label class="control-label" for="inputError"><i
class="feather icon-x-circle"></i>
{{ $message }}</label><br />
@endforeach
@endif
<input name="{{ $name }}[values][{{ $loop->index }}]"
value="{{ old("{$column}.values.{$k}", $v) }}" class="form-control" />
</div>
</div>
</td>
<td class="form-group">
<div>
<div class="{{ $class }}-remove btn btn-white btn-sm pull-right">
<i class="feather icon-trash"> </i>{{ __('admin.remove') }}
</div>
</div>
</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td>
{{-- 新增按钮 --}}
<div class="{{ $class }}-add btn btn-primary btn-outline btn-sm pull-right">
<i class="feather icon-save"></i> {{ __('admin.new') }}
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<template class="{{ $class }}-tpl">
<tr>
<td>
{{-- 这里进行操作 --}}
@if ($options)
<div class="{{ $viewClass['field'] }}">
<select class="form-control {{ $class }}" style="width: 100%;"
name="{{ $name }}[keys][{key}]" {!! $attributes !!}>
<option value=""></option>
@foreach ($options as $select => $option)
<option value="{{ $select }}"
{{ Dcat\Admin\Support\Helper::equal($select, old($column, $value)) ? 'selected' : '' }}>
{{ $option }}</option>
@endforeach
</select>
</div>
@else
<div class="form-group ">
<div class="col-sm-12">
<div class="help-block with-errors"></div>
<input name="{{ $name }}[keys][{key}]" class="form-control" required />
</div>
</div>
@endif
</td>
<td>
<div class="form-group ">
<div class="col-sm-12">
<div class="help-block with-errors"></div>
<input name="{{ $name }}[values][{key}]" class="form-control" />
</div>
</div>
</td>
<td class="form-group">
<div>
<div class="{{ $class }}-remove btn btn-white btn-sm pull-right">
<i class="feather icon-trash"> </i>{{ __('admin.remove') }}
</div>
</div>
</td>
</tr>
</template>
配置到启动文件 app\Admin\bootstrap.php
// 最后增加即可
Dcat\Admin\Form::extend('selectKeyValue', \App\ExtField\SelectKeyValue::class);
使用
protected function form()
{
return Form::make(new User(), function (Form $form) {
$form->selectKeyValue('config')
->options([
'name' => '姓名',
'age' => '年龄'
]);
});
}