# How do I add a custom field to the new and edit product page?

In this mini tutorial we will add a notes field to the product new and edit page for the product and each variant.

This mini tutorial assumes that you have a module setup or you’re happy working from the app service provider (using the `boot` method). You can see how to set up a module [here](https://support.aerocommerce.com/books/modules/page/how-do-i-create-a-custom-module).

## 1. Adding the database migration

To get started we will add a migration file that will update the products and variants tables to have a notes column:

```php
class AddNotesFieldsToProductsAndVariants extends \Illuminate\Database\Migrations\Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       \Illuminate\Support\Facades\Schema::table('products', function (\Illuminate\Database\Schema\Blueprint $table) {
           $table->string('notes')->nullable()->after('description');
       });

       \Illuminate\Support\Facades\Schema::table('variants', function (\Illuminate\Database\Schema\Blueprint $table) {
           $table->string('notes')->nullable()->after('name');
       });
   }

   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       \Illuminate\Support\Facades\Schema::table('products', function (\Illuminate\Database\Schema\Blueprint $table) {
           $table->dropColumn('notes');
       });

       \Illuminate\Support\Facades\Schema::table('variants', function (\Illuminate\Database\Schema\Blueprint $table) {
           $table->dropColumn('notes');
       });
   }
}
```

## 2. Adding the slot view

Now we’ll create two views, one that will be injected for the product and one that will be injected for the variants. These views will have a text area in them for the notes input.

### `product-notes-field.blade.php`

```html
<div class="card mt-4">
   <label for="notes" class="block mb-2">Notes</label>
   <textarea name="notes" id="notes" v-model="product.notes" class="w-full"></textarea>
</div>
```

### `variant-notes-field.blade.php`

```html
<div class="p-4" v-if="!isSimpleProduct">
   <label :for="'variant-notes-' + key" class="block mb-2">Notes</label>
   <textarea :name="'variants[' + key + '][notes]'" :id="'variant-notes-' + key" v-model="variants[key].notes" class="w-full"></textarea>
</div>
```

After creating the views we will inject them into the relevant slots using the `Aero\Admin\AdminSlot::inject()` method:

```php
\Aero\Admin\AdminSlot::inject('catalog.product.new.cards', 'acme::product-notes-field');
\Aero\Admin\AdminSlot::inject('catalog.product.edit.cards', 'acme::product-notes-field');

\Aero\Admin\AdminSlot::inject('catalog.product.new.variant', 'acme::variant-notes-field');
\Aero\Admin\AdminSlot::inject('catalog.product.edit.variant', 'acme::variant-notes-field');
```

## 3. Making the notes save

### 3.1. Make the notes fillable

We need to make the notes fillable as Laravel will only mass assign [fillable attributes](https://laravel.com/docs/6.x/eloquent#mass-assignment):

```php
\Aero\Catalog\Models\Product::makeFillable('notes');
\Aero\Catalog\Models\Variant::makeFillable('notes');
```

### 3.2. Adding validation for notes field

To validate the notes, we need to extend the product create and update requests:

```php
\Aero\Admin\Http\Requests\Catalog\CreateProductRequest::expects('notes', 'nullable|string');
\Aero\Admin\Http\Requests\Catalog\UpdateProductRequest::expects('notes', 'nullable|string');

\Aero\Admin\Http\Requests\Catalog\CreateProductRequest::expects('variants.*.notes', 'nullable|string');
\Aero\Admin\Http\Requests\Catalog\UpdateProductRequest::expects('variants.*.notes', 'nullable|string');
```

<p class="callout info">See [here](https://support.aerocommerce.com/books/general-Paw/page/how-can-i-extend-an-existing-request) for more guidance on extending requests.</p>

### 3.3. Adding notes to the transfomers

Adding notes to the transformers will ensure that it’s available in our views through Vue:

```php
\Aero\Admin\Transformers\ProductTransformer::add(function ($data) {
    return [
        'notes' => $data['product']->notes ?? '',
    ];
});

\Aero\Admin\Transformers\VariantTransformer::add(function ($data) {
    return [
        'notes' => $data['variant']->notes ?? '',
    ];
});

\Aero\Admin\Transformers\BaseVariantTransformer::add(function ($data) {
    return [
        'notes' => '',
    ];
});
```

<p class="callout info">See [here](https://support.aerocommerce.com/books/admin/chapter/transformers) for more information about transformers.</p>

---

## Complete Service Provider

```php
<?php

namespace Aerocargo\Acme;

use Aero\Admin\AdminSlot;
use Aero\Admin\Http\Requests\Catalog\CreateProductRequest;
use Aero\Admin\Http\Requests\Catalog\UpdateProductRequest;
use Aero\Admin\Transformers\BaseVariantTransformer;
use Aero\Admin\Transformers\ProductTransformer;
use Aero\Admin\Transformers\VariantTransformer;
use Aero\Catalog\Models\Product;
use Aero\Catalog\Models\Variant;
use Aero\Common\Providers\ModuleServiceProvider;

class ServiceProvider extends ModuleServiceProvider
{
    public function setup()
    {
        if ($this->app->runningInConsole()) {
            $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
        }

        $this->loadViewsFrom(__DIR__.'/../resources/views', 'acme');

        AdminSlot::inject('catalog.product.new.cards', 'acme::product-notes-field');
        AdminSlot::inject('catalog.product.edit.cards', 'acme::product-notes-field');
      
        AdminSlot::inject('catalog.product.new.variant', 'acme::variant-notes-field');
        AdminSlot::inject('catalog.product.edit.variant', 'acme::variant-notes-field');

        Product::makeFillable('notes');
        Variant::makeFillable('notes');

        CreateProductRequest::expects('notes', 'nullable|string');
        UpdateProductRequest::expects('notes', 'nullable|string');

        CreateProductRequest::expects('variants.*.notes', 'nullable|string');
        UpdateProductRequest::expects('variants.*.notes', 'nullable|string');

        ProductTransformer::add(function ($data) {
            return [
                'notes' => $data['product']->notes ?? '',
            ];
        });

        VariantTransformer::add(function ($data) {
            return [
                'notes' => $data['variant']->notes ?? '',
            ];
        });

        BaseVariantTransformer::add(function ($data) {
            return [
                'notes' => '',
            ];
        });
    }
}
```