logo

字段

概述

Nova 随附各种字段类型,但有时你可能需要的字段类型并不是开箱即有的。因此,Nova 允许你创建自定义字段。自定义字段由三个 Vue 组件组成,它们决定了字段在不同上下文中的显示方式。

定义字段

自定义字段可使用 nova:field Artisan 命令生成。默认情况下,所有新字段都将放在应用程序的 nova-components 目录中。使用nova:field命令生成字段时,传递给命令的字段名称应遵循 Composer 的 vendor/package 格式。因此,如果我们要创建一个 color-picker 字段,可以运行以下命令:

php
php artisan nova:field acme/color-picker

生成字段时,Nova 会提示你安装字段的 NPM 依赖项、编译其资产并更新应用程序的 composer.json 文件。所有自定义字段都会在应用程序中注册为 Composer 「路径」存储库

Nova 字段包含构建字段所需的所有脚手架。每个字段甚至都包含自己的 composer.json 文件,可以在 GitHub 或你选择的源控制提供商上与全世界共享。

注册字段

Nova 字段可在资源的 fields 方法中注册。该方法返回资源可用字段的数组。要注册字段,请将字段添加到此方法返回的字段数组中:

php
use Acme\ColorPicker\ColorPicker;

/**
 * 获取资源显示的字段。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function fields(NovaRequest $request)
{
    return [
        ID::make('ID', 'id')->sortable(),

        ColorPicker::make('Color'),
    ];
}

字段选项

通常,你需要允许字段的用户自定义字段的运行时配置选项。为此,你可以在字段类上公开方法。这些方法可调用字段的底层 withMeta 方法,以向字段的元数据添加信息,这些信息将在字段的 Vue 组件中提供。withMeta 方法接受一个键/值选项数组:

php
<?php

namespace Acme\ColorPicker;

use Laravel\Nova\Fields\Field;

class ColorPicker extends Field
{
    /**
     * 字段的组成部分。
     *
     * @var string
     */
    public $component = 'color-picker';

    /**
     * 设置颜色选择器可选择的色调。
     *
     * @param  array  $hues
     * @return $this
     */
    public function hues(array $hues)
    {
        return $this->withMeta(['hues' => $hues]);
    }
}

获取字段选项

你的字段的 Vue 组件会收到一个 field Vue propfield 属性提供了对任何可用字段选项的访问:

js
const hues = this.field.hues;

创建字段

Nova 生成的每个字段都有自己的服务提供者和 "field" 类。以 color-picker 字段为例,字段类将位于 src/ColorPicker.php

字段的服务提供者也位于字段的 src 目录中,并在字段的 composer.json 文件的 extra 部分注册,以便 Laravel 自动加载。

列表字段

当Nova生成你的字段时,它会创建一个 resourcesjscomponentsIndexField.vue vue组件。当字段显示在资源索引页上时,此组件包含字段的模板和逻辑。默认情况下,该组件只是在一个简单的 <span> 元素中显示字段的值;但是,你可以根据需要自由修改此字段组件。

详情字段

创建字段时,Nova 还会创建一个 resources/js/components/DetailField.vue Vue 组件。该组件包含字段在资源详情页显示时的模板和逻辑。默认情况下,该模板包含显示字段值所需的必要标记。不过,你可以根据应用程序的需要自由调整该模板。

表单字段

最后,Nova 会创建一个 resources/js/components/FormField.vue Vue 组件。该组件包含字段在创建或更新表单中显示时的模板和逻辑。默认情况下,该模板包含一个简单的 input 控件,用于修改字段的底层值;不过,你可以自由定制该模板。例如,我们可以更新模板以显示一个颜色选择器控件:

vue
<template>
    <DefaultField :field="field">
        <template #field>
            <input :id="field.name" type="color"
                class="w-full form-control form-input form-input-bordered"
                :class="errorClasses"
                :placeholder="field.name"
                v-model="value"
            />

            <p v-if="hasError" class="my-2 text-danger">
                {{ firstError }}
            </p>
        </template>
    </DefaultField>
</template>

<script>
import { FormField, HandlesValidationErrors } from 'laravel-nova'

export default {
  mixins: [FormField, HandlesValidationErrors],

  //
}
</script>

设置表单值

在创建或更新资源之前,Nova 会要求表单上的每个字段用 键/值对「填充」传出的 FormData 对象。每个字段可根据需要向 FormData 添加任意数量的元素。这可在你的 FormField.vue 文件的 fill 方法中完成:

js
/**
 * 用字段的内部值填充给定的 FormData 对象。
 */
fill(formData) {
  this.fillIfVisible(formData, this.fieldAttribute, this.value || '')
}

表单依赖字段

默认情况下,所有自定义字段都将使用 FormField 混合元素创建。但是,如果你正在创建 依赖字段,则应将 FormField 替换为 DependentFormField

js
// 之前 ...
import { FormField, HandlesValidationErrors } from 'laravel-nova'

export default {
  mixins: [FormField, HandlesValidationErrors],

  //
}

// 之后...
import { DependentFormField, HandlesValidationErrors } from 'laravel-nova'

export default {
  mixins: [DependentFormField, HandlesValidationErrors],

  //
}

接下来,在 Vue 模板中,通常应使用 this.currentField 而不是 this.field 来引用字段:

vue
<template>
  <DefaultField :field="currentField" :errors="errors">
    <template #field>
      <input
        :id="currentField.uniqueKey"
        type="text"
        class="w-full form-control form-input form-input-bordered"
        :class="errorClasses"
        :placeholder="currentField.placeholder"
        v-model="value"
      />

      <p v-if="hasError" class="my-2 text-danger">
        {{ firstError }}
      </p>
    </template>
  </DefaultField>
</template>

<script>
import { DependentFormField, HandlesValidationErrors } from 'laravel-nova'

export default {
  mixins: [DependentFormField, HandlesValidationErrors],

  //
}
</script>

接下来,别忘了在你的 Field 类上使用 Laravel\Nova\Fields\SupportsDependentFields 特性:

php
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\SupportsDependentFields;

class ColorPicker extends Field
{
    use SupportsDependentFields;

    // ...
}

水合模型

默认情况下,在保存模型时,你的字段类只需将传入的表单字段值复制到字段的关联模型属性中。不过,你可以自定义字段如何水合资源模型。要做到这一点,请覆盖字段类上的 fillAttributeFromRequest 方法:

php
<?php

namespace Acme\ColorPicker;

use Illuminate\Support\Str;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Http\Requests\NovaRequest;

class ColorPicker extends Field
{
    /**
     * 字段的组成部分。
     *
     * @var string
     */
    public $component = 'color-picker';

    /**
     * 用数据填充模型的属性。
     *
     * @param  \Illuminate\Database\Eloquent\Model|\Laravel\Nova\Support\Fluent  $model
     * @param  mixed  $value
     * @param  string  $attribute
     * @return void
     */
    public function fillModelWithData(mixed $model, mixed $value, string $attribute)
    {
        $attributes = [Str::replace('.', '->', $attribute) => $value];

        $model->forceFill($attributes);
    }
}

该方法接收多个参数。当然,它接收传入的 HTTP 请求和正在更新的模型。该方法还会接收 $requestAttribute,即 HTTP 请求中传入表单字段的名称。此外,它还会接收 $attribute,即字段值应放置的模型属性名称。

资源

Nova 生成字段时,会为你生成 resources/jsresources/css 目录。这些目录包含字段的 JavaScript 和 CSS。

注册资源

你的 Nova 字段服务提供商会注册你的字段编译资源,以便 Nova 前端可以使用这些资源:

php
use Laravel\Nova\Nova;
use Laravel\Nova\Events\ServingNova;

/**
 * 引导任何应用服务。
 *
 * @return void
 */
public function boot()
{
    Nova::serving(function (ServingNova $event) {
        Nova::script('stripe-inspector', __DIR__.'/../dist/js/field.js');
        Nova::style('stripe-inspector', __DIR__.'/../dist/css/field.css');
    });
}

JavaScript 引导和路由

你的组件将在 resources/js/field.js 文件中引导和注册。你可以根据需要修改该文件或在此注册其他组件。

编译资源

Nova 字段包含一个 webpack.mix.js 文件,该文件在 Nova 创建工具时生成。你可以使用 NPM devprod 命令构建你的工具:

bash
# 准备 Laravel Nova 的依赖项...
npm run nova:install

# 为本地开发编译资源...
npm run dev

# 编译并最小化资源...
npm run prod

此外,你还可以运行 NPM watch 命令,在资源发生变化时自动编译它们:

bash
npm run watch

nova:install NPM 命令

nova:install NPM 命令会安装 Nova 内置字段使用的 mixins,以便在你的字段中使用。更多信息请参阅 Nova mixins 文档。