Skip to content
Muhammad Syifa edited this page Oct 8, 2017 · 18 revisions

Form Model adalah library khusus framework laravel untuk mempermudah pembuatan form create dan edit data berdasarkan model tertentu.

Kebutuhan

  • PHP >= 7.0
  • Laravel 5.5

Instalasi

Install Form Model

Buka terminal/cmd, masuk ke direktori proyek laravel kamu. Kemudian ketikkan perintah composer berikut:

composer require laraspells/form-model:dev-master

Publish Konfigurasi (opsional)

Jika kamu ingin melakukan perubahan pada konfigurasi view form, view fields, dsb. Kamu dapat melakukan publish konfigurasi terlebih dahulu menggunakan perintah dibawah ini:

php artisan vendor:publish --provider=LaraSpells\\FormModel\\ServiceProvider --tag=config

Memulai

Untuk sementara, silahkan simak video ini untuk melihat alur kerja form model.

Konsep

Untuk dapat lebih memahami potensi dan batasan form model, kamu perlu mengetahui bagaimana form model bekerja.

Pada dasarnya form model hanyalah sebuah objek yang menampung spesifikasi formulir pada (eloquent) model tertentu yang ingin dilakukan proses create atau update. Spesifikasi-spesifikasi ini didefinisikan melalui array dan method-method yang telah disediakan.

Selanjutnya form model memanfaatkan spesifikasi tersebut untuk melakukan rendering dan submitting (proses create/update model).

Untuk melakukan rendering, form model memaksimalkan kemampuan Blade pada laravel, khususnya fitur @include, @component, dsb untuk management view. Untuk contoh bagaimana form model mengelola file viewnya, kamu dapat melihat pada folder form bs3 ini.

Untuk lebih jelasnya, perhatikan setup form model Product dibawah ini:

// file: app/Http/Controllers/ProductController.php
...

protected function form(Product $product)
{
    return FormModel::make($product, [
        'name' => [
            'input' => 'text',
            'label' => 'Name',
            'maxlength' => 120,
            'rules' => 'required|max:120'
        ],
        'slug' => [
            'input' => 'text',
            'label' => 'Slug',
            'maxlength' => 120,
            'rules' => 'required|max:120|unique:products,slug'
        ],
        'description' => [
            'input' => 'textarea',
            'label' => 'Description',
            'rules' => 'required'
        ],
        'image' => [
            'input' => "image",
            'label' => "Image",
            'delete_old_file' => true,
            'upload_disk' => 'uploads',
            'upload_path' => 'product/images',
            'rules' => 'required|image|max:2048'
        ]
    ]);
}

...

Form model tersebut, jika di render() menggunakan form template bs3, akan menghasilkan struktur view seperti dibawah ini:

Concept: View Structure

Dan tentu saja, kamu dapat mengirimkan view data tambahan ke setiap bagian view tersebut, ataupun jika kamu ingin menggunakan field khusus yang menggunakan plugin seperti ckeditor, tinymce, input mask, dsb, kamu dapat menambahkan view field type kamu sendiri dan mendaftarkannya pada file konfigurasi, ataupun melalui method withInputViews.

Hal yang perlu kamu ketahui selanjutnya, form model memanfaatkan property exists (boolean) pada Eloquent. Property exists ini mengindikasikan sebuah model terdapat pada database atau tidak. Form model memanfaatkan property ini untuk menentukan proses yang dilakukan adalah proses create atau proses edit.

Contoh:

$this->form(new Product)->render(); // will render form create product
$this->form(Product::findOrFail(1))->render(); // will render form edit product

$this->form(new Product)->submit($request); // will insert new product
$this->form(Product::findOrFail(1))->submit($request); // will update product

Panduan

Set Parameter Field Khusus Proses Create/Update

Misalkan kamu ingin set readonly menjadi true pada field kode_barang hanya pada saat update. Kamu dapat menggunakan if_update seperti contoh di bawah ini:

'kode_barang' => [
    'input' => 'text',
    'label' => 'Kode Barang',
    'rules' => 'required|unique:barang,kode_barang',
    'if_update' => [
        'readonly' => true
    ]
]

Dengan begitu, jika kamu sedang melakukan proses update, parameter readonly yang bernilai true akan dikirim ke view input text.

Begitu juga dengan parameter khusus create, kamu dapat menggunakan if_create.

Menambahkan Field Khusus

Misalkan kamu ingin menambahkan field type select2 yang menggunakan plugin select2. Kamu dapat melakukan beberapa tahap berikut:

1) Membuat View Field Select2

Buat sebuah file view baru di resources/views/partials/fields/select2.blade.php. Karena select2 ini berupa select, kita dapat copy-paste isi dari field select di form template bs3.

@php
$id = "input-{$name}";
$label = isset($label)? $label : ucwords(snake_case(camel_case($name), ' '));
$required = isset($required)? (bool) $required : false;
$empty_option = isset($empty_option)? $empty_option : 'Pick '.$label;
$value = isset($value)? $value : '';
@endphp

@component('form-model::bs3.fields.wrapper', [
  'name' => $name, 
  'label' => $label,
  'required' => $required
])

  @if(isset($groupLeft) OR isset($groupRight))
    <div class="input-group">
    {!! $groupLeft or '' !!}
  @endif

  <select
    class="form-control select2"
    name="{{ $name }}"
    id="{{ $id }}"
    {{ $required? 'required' : '' }}>
    @if($empty_option)
    <option value="">{{ $empty_option }}</option>
    @endif
    @foreach($options as $option)
      @if(isset($option['options']))
        <optgroup label="{{ $option['label'] }}" {!! isset($option['attributes'])? html_attributes($option['attributes']) : "" !!}>
          @foreach($option['options'] as $opt)
          <option value="{{ $opt['value'] }}" {{ $value == $opt['value']? 'selected' : '' }} {!! isset($opt['attributes'])? html_attributes($opt['attributes']) : "" !!}>{{ $opt['label'] }}</option>
          @endforeach
        </optgroup>
      @else
        <option value="{{ $option['value'] }}" {{ $value == $option['value']? 'selected' : '' }} {!! isset($option['attributes'])? html_attributes($option['attributes']) : "" !!}>{{ $option['label'] }}</option>
      @endif
    @endforeach
  </select>

  @if(isset($groupLeft) OR isset($groupRight))
    {!! $groupRight or '' !!}
    </div>
  @endif

@endcomponent

@css('vendor/admin-lte/plugins/select2/select2.min.css')
@js('vendor/admin-lte/plugins/select2/select2.min.js')
@script('init-select2')
<script>
  $('select.select2').select2({})
</script>
@endscript

Directive @css, @js, dan @script merupakan directive khusus dari komponen asset-collector. Directive tersebut berfungsi untuk mendaftarkan file css, js, dan kode javascript, dan mencegahnya agar tidak duplikat semisal kamu menggunakan lebih dari satu field select2 pada form kamu.

2) Mendaftarkan Field Select2 Pada Konfigurasi

Buka file config/form-model.php. Jika tidak ada, silahkan publish terlebih dahulu.

Kemudian tambahkan baris berikut:

return [

    'default_form' => 'bs3',

    'forms' => [
        'bs3' => [
            'form' => 'form-model::bs3.form',
            'inputs' => [
                ...
                'select2' => 'partials.fields.select2', // << tambahkan ini
            ]
        ]
    ]

];

Jika sudah, jangan lupa simpan.

Setelah itu kamu dapat menggunakan 'input' => 'select2' pada form model kamu.

Menggunakan Field yang Tidak Terdaftar pada Table

Adakalanya, kita memiliki sebuah kolom yang berisi data komposit (gabungan dari beberapa nilai). Misalnya kita memiliki database user yang hanya memiliki kolom name, tetapi kita ingin memisahkan inputannya menjadi first_name dan last_name.

Pada kasus seperti itu, kamu dapat menggunakan method beforeSave, dan parameter tambahan render_value pada field-field tambahan tersebut seperti contoh dibawah ini:

// file: app/Http/Controllers/UserController.php
...

protected function form(User $user)
{
    return FormModel::make($user, [
        'first_name' => [
            'input' => 'text',
            'label' => 'First Name',
            'maxlength' => 60,
            'rules' => 'required|max:60',
            'render_value' => function($value) {
                return $this->getModel()->getFirstName(); // add this method to User model
            }
        ],
        'last_name' => [
            'input' => 'text',
            'label' => 'Last Name',
            'maxlength' => 60,
            'rules' => 'required|max:60',
            'render_value' => function($value) {
                return $this->getModel()->getLastName(); // add this method to User model
            }
        ],
        ...
    ])
    ->beforeSave(function($user) {
        $req = $this->getRequest();
        $user->name = $req->get('first_name').' '.$req->get('last_name');
    });
}

...

Parameter render_value berfungsi untuk set nilai yang akan di render ke view field. Sedangkan beforeSave digunakan untuk set callback yang akan dieksekusi tepat sebelum eloquent model melakukan method save().