Laravel Form builder for version 5+!

Overview

Build Status Coverage Status Total Downloads Latest Stable Version License

Laravel 5 form builder

Join the chat at https://gitter.im/kristijanhusak/laravel-form-builder

Form builder for Laravel 5 inspired by Symfony's form builder. With help of Laravels FormBuilder class creates forms that can be easy modified and reused. By default it supports Bootstrap 3.

Laravel 4

For Laravel 4 version check laravel4-form-builder.

Bootstrap 4 support

To use bootstrap 4 instead of bootstrap 3, install laravel-form-builder-bs4.

Upgrade to 1.6

If you upgraded to >1.6.* from 1.5.* or earlier, and having problems with form value binding, rename default_value to value.

More info in changelog.

Documentation

For detailed documentation refer to https://kristijanhusak.github.io/laravel-form-builder/.

Changelog

Changelog can be found here.

Installation

Using Composer

composer require kris/laravel-form-builder

Or manually by modifying composer.json file:

{
    "require": {
        "kris/laravel-form-builder": "1.*"
    }
}

And run composer install

Then add Service provider to config/app.php

    'providers' => [
        // ...
        Kris\LaravelFormBuilder\FormBuilderServiceProvider::class
    ]

And Facade (also in config/app.php)

    'aliases' => [
        // ...
        'FormBuilder' => Kris\LaravelFormBuilder\Facades\FormBuilder::class
    ]

Notice: This package will add laravelcollective/html package and load aliases (Form, Html) if they do not exist in the IoC container.

Quick start

Creating form classes is easy. With a simple artisan command:

php artisan make:form Forms/SongForm --fields="name:text, lyrics:textarea, publish:checkbox"

Form is created in path app/Forms/SongForm.php with content:

<?php

namespace App\Forms;

use Kris\LaravelFormBuilder\Form;
use Kris\LaravelFormBuilder\Field;

class SongForm extends Form
{
    public function buildForm()
    {
        $this
            ->add('name', Field::TEXT, [
                'rules' => 'required|min:5'
            ])
            ->add('lyrics', Field::TEXTAREA, [
                'rules' => 'max:5000'
            ])
            ->add('publish', Field::CHECKBOX);
    }
}

If you want to instantiate empty form without any fields, just skip passing --fields parameter:

php artisan make:form Forms/PostForm

Gives:

<?php

namespace App\Forms;

use Kris\LaravelFormBuilder\Form;

class PostForm extends Form
{
    public function buildForm()
    {
        // Add fields here...
    }
}

After that instantiate the class in the controller and pass it to view:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Kris\LaravelFormBuilder\FormBuilder;

class SongsController extends BaseController {

    public function create(FormBuilder $formBuilder)
    {
        $form = $formBuilder->create(\App\Forms\SongForm::class, [
            'method' => 'POST',
            'url' => route('song.store')
        ]);

        return view('song.create', compact('form'));
    }

    public function store(FormBuilder $formBuilder)
    {
        $form = $formBuilder->create(\App\Forms\SongForm::class);

        if (!$form->isValid()) {
            return redirect()->back()->withErrors($form->getErrors())->withInput();
        }

        // Do saving and other things...
    }
}

Alternative example:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Kris\LaravelFormBuilder\FormBuilder;
use App\Forms\SongForm;

class SongsController extends BaseController {

    public function create(FormBuilder $formBuilder)
    {
        $form = $formBuilder->create(SongForm::class, [
            'method' => 'POST',
            'url' => route('song.store')
        ]);

        return view('song.create', compact('form'));
    }

    public function store(FormBuilder $formBuilder)
    {
        $form = $formBuilder->create(SongForm::class);

        if (!$form->isValid()) {
            return redirect()->back()->withErrors($form->getErrors())->withInput();
        }

        // Do saving and other things...
    }
}

If you want to store a model after a form submit considerating all fields are model properties:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Kris\LaravelFormBuilder\FormBuilder;
use App\SongForm;

class SongFormController extends Controller
{
    public function store(FormBuilder $formBuilder)
    {
        $form = $formBuilder->create(\App\Forms\SongForm::class);
        $form->redirectIfNotValid();
        
        SongForm::create($form->getFieldValues());

        // Do redirecting...
    }

You can only save properties you need:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Kris\LaravelFormBuilder\FormBuilder;
use App\SongForm;

class SongFormController extends Controller
{
    public function store(FormBuilder $formBuilder, Request $request)
    {
        $form = $formBuilder->create(\App\Forms\SongForm::class);
        $form->redirectIfNotValid();
        
        $songForm = new SongForm();
        $songForm->fill($request->only(['name', 'artist'])->save();

        // Do redirecting...
    }

Or you can update any model after form submit:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Kris\LaravelFormBuilder\FormBuilder;
use App\SongForm;

class SongFormController extends Controller
{
    public function update(int $id, Request $request)
    {
        $songForm = SongForm::findOrFail($id);

        $form = $this->getForm($songForm);
        $form->redirectIfNotValid();

        $songForm->update($form->getFieldValues());

        // Do redirecting...
    }

Create the routes

// app/Http/routes.php
Route::get('songs/create', [
    'uses' => '[email protected]',
    'as' => 'song.create'
]);

Route::post('songs', [
    'uses' => '[email protected]',
    'as' => 'song.store'
]);

Print the form in view with form() helper function:

<!-- resources/views/song/create.blade.php -->

@extends('app')

@section('content')
    {!! form($form) !!}
@endsection

Go to /songs/create; above code will generate this html:

<form method="POST" action="http://example.dev/songs">
    <input name="_token" type="hidden" value="FaHZmwcnaOeaJzVdyp4Ml8B6l1N1DLUDsZmsjRFL">
    <div class="form-group">
        <label for="name" class="control-label">Name</label>
        <input type="text" class="form-control" id="name">
    </div>
    <div class="form-group">
        <label for="lyrics" class="control-label">Lyrics</label>
        <textarea name="lyrics" class="form-control" id="lyrics"></textarea>
    </div>
    <div class="form-group">
        <label for="publish" class="control-label">Publish</label>
        <input type="checkbox" name="publish" id="publish">
    </div>
</form>

Or you can generate forms easier by using simple array

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Kris\LaravelFormBuilder\FormBuilder;
use Kris\LaravelFormBuilder\Field;
use App\Forms\SongForm;

class SongsController extends BaseController {

    public function create(FormBuilder $formBuilder)
    {
        $form = $formBuilder->createByArray([
                        [
                            'name' => 'name',
                            'type' => Field::TEXT,
                        ],
                        [
                            'name' => 'lyrics',
                            'type' => Field::TEXTAREA,
                        ],
                        [
                            'name' => 'publish',
                            'type' => Field::CHECKBOX
                        ],
                    ]
            ,[
            'method' => 'POST',
            'url' => route('song.store')
        ]);

        return view('song.create', compact('form'));
    }
}

Contributing

Project follows PSR-2 standard and it's covered with PHPUnit tests. Pull requests should include tests and pass Travis CI build.

To run tests first install dependencies with composer install.

After that tests can be run with vendor/bin/phpunit

Issues
  • Many to Many collection displayed as select

    Many to Many collection displayed as select

    Not really an issue but I wouldn't know where else to ask.

    I have a Movie with a belongsToMany languages association.

    Let's say a Movie has 2 languages (english and spanish).

    I'm trying to show 2 selects with a list of all languages, where the first one has 'english' as selected and the second one has 'spanish'. option value should be the language id.

    This is my attempt, within MovieForm:

    $this
    ->add('languages', 'collection', [
      'type' => 'select',
      'property' => 'name',
      'choices' => $this->model->languages()->lists('id', 'name')
    ])
    

    This is obviously wrong (shows an empty select), but I'm not sure how to accomplish this, the documentation is not very clear about this. I'd like to avoid using a child LanguageForm as it would just display a select.

    opened by koichirose 36
  • Pass Model to ChildForm

    Pass Model to ChildForm

    How do i pass a model reference to childs forms?

        public function buildForm()
        {
            $this
                ->add('User', 'form', [
                    'class' => 'App\Forms\UserForm',
                    'formOptions' => [],
                    'model' => $user,
                ])->add('Company', 'form', [
                    'class' => 'App\Forms\CompanyForm',
                ]);
        }
    

    'model'=>$user is not working...form is rendered, but empty

    opened by mstaack 33
  • Fix `mergeOptions` behavior

    Fix `mergeOptions` behavior

    \Kris\LaravelFormBuilder\FormHelper::mergeOptions merges options with rules option behavior incorrectly. It should replace the rules entirely or just appends new rules. The current strategy may cause the merged rules duplicated, and has no way to "replace" the default rules entirely.

    opened by yaquawa 24
  • Add default classes to a field.

    Add default classes to a field.

    It's currently only possible to set one class for a form field. When you set a default class in your laravel-form-builder.php file and then set a new class in your form builder array then only the last class will be added.

    In this commit I've created the following things:

    1. Default classes on the field wrapper for all fields (form-TYPE) in addition to the class that you set in wrapper_class.
    2. Additional class on the field wrapper for choice fields (form-TYPE and form-type-CHOICETYPE
    3. Wrapper class on the choice options wrapper (form-CHOICETYPE)
    4. You can add additional classes without overwriting the defaults (I've added a array_merge_map_recursive function for this).
    opened by jvdlaar 23
  • Laravel 5.2.32 or greater breaks form

    Laravel 5.2.32 or greater breaks form

    When updating to Laravel 5.2.32 or greater, I get the following error when trying to display a form with a button. Removing the button works.

    Relationship method must return an object of type lluminate\Database\Eloquent\Relations\Relation

    /* EditMediaForm.php */
    
    public function buildForm()
    {
         $this->add('filename', 'text')
             ->add('alt_attribute', 'text')
             ->add('save', 'submit', ['attr' => ['class' => 'btn btn-primary']]);
    }
    
    opened by vincehollywood 23
  • Add form composition

    Add form composition

    This PR adds the ability to take a child form and add its fields directly to the parent form.

    Added makeField() as an abstracted method of generating the FormField Added compose which is used the same way as add() just only needing $options and the $modify flag. It creates the child form as usual via the new makeField() function, then just adds all the fields from that child form, to the parent form.

    I've thrown this together as it fixed my issue of trying to use child forms to help with composition of forms but it messed up using model binding, and this is the best solution anyway I just hadnt thought of it till now :P

    opened by theshaunwalker 23
  • Call to undefined method Illuminate\Events\Dispatcher::fire() in Laravel 5.8

    Call to undefined method Illuminate\Events\Dispatcher::fire() in Laravel 5.8

    issue with the latest compatibility

    opened by nekromoff 22
  • Set data for child forms and create named forms.

    Set data for child forms and create named forms.

    Not sure if this was bug or missing feature, but I was not able to pass data for child forms. Now its possible. Also added new method in FormBuilder to create named forms like Symfony does. Form field names become like youname[fieldname].

    opened by tormit 22
  • Add a `ContainerType` field

    Add a `ContainerType` field

    This PR adds a ContainerType field which solves #572. It was branched from #577 , so you might only want to see the diff at https://github.com/kristijanhusak/laravel-form-builder/commit/d016cba31cabfded082919f0bebaa8efa106bc06

    ContainerType field acts as a "container", which means even it has children fields, but it'll make the hierarchy of it's children as same as itself. In other words, the field's attributes and rules are be replaced by its children's ones(similar to ChildFormType). With this, users can easily implement fieldset or similar things by just specifying a custom template.

    Usage

    <?php
    
    namespace App\Forms;
    
    class MyForm extends Form
    {
        public function buildForm()
        {
            $this
                ->add('date', 'container', [
                    'label' => 'DATE',
                    'fields' => [
                        [
                            'type' => 'date',
                            'name' => 'start_date',
                            'options' => [
                                'label' => false,
                                'rules' => 'required|date|max:255',
                            ],
                        ],
                        [
                            'type' => 'date',
                            'name' => 'end_date',
                            'rules' => 'date|max:255',
                            'options' => [
                                'label' => false,
                                'rules' => 'date|max:255',
                            ],
                        ]
                    ],
                ]);
        }
    }
    
    opened by yaquawa 20
  • #246 +Form->getValidatedValues()

    #246 +Form->getValidatedValues()

    Adds a public $form->getValidatedValues() function to extract all Request values according to the submitted form, not according to the submitted data. Uses all fields' getAllAttributes() to collect a flat list of all attributes, including all child forms and theirs etc.

    The main function (getValidatedValues) is somewhat of a misnomer, because it doesn't actually validate, and the returned values don't have to be validated in order to call it, but I couldn't find a better name.

    Usage: instead of

    $values = $request->all();
    

    call

    $values = $form->getValidatedValues();
    
    opened by rudiedirkx 19
  • getFieldValues + disabled fields

    getFieldValues + disabled fields

    getFieldValues() ignores disabled fields (which the browser doesn't send), and accepts null as its value. It should completely ignore input for disabled fields, and not include them in the output, just like for static fields.

    PR later.

    bug 
    opened by rudiedirkx 0
  • choice checkboxes required attributes bugfix

    choice checkboxes required attributes bugfix

    Never copy the required attr to a ChoiceType's children if they're checkboxes. For select or radiobuttons it's okay, but not for checkboxes, because that makes every individual checkbox required.

    opened by rudiedirkx 0
  • Question: how to control where a collection is rendered

    Question: how to control where a collection is rendered

    Hi

    I'm trying to figure out how to get a few collections rendered in the correct place

    I have 5 fields that I would like to have in the beginning and then two collections as two rows

    But I can figure out hw to get the non collection fields rendered an then the collections - the first entry of the collection is in the right place, but then when 'adding' to the collection the new entries gets added to the top of the form

    I'm using the sample from the documentation

    help wanted 
    opened by rabol-teetrack 5
  • I am getting an error while installing. (ide-helper / composer)

    I am getting an error while installing. (ide-helper / composer)

    I'm getting an error installing with Composer

    Laravel version: 8.x

    % COMPOSER_MEMORY_LIMIT=-1 composer require kris/laravel-form-builder       
    Using version ^1.40 for kris/laravel-form-builder
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Nothing to install or update
    Package fzaninotto/faker is abandoned, you should avoid using it. No replacement was suggested.
    Generating optimized autoload files
    > Illuminate\Foundation\ComposerScripts::postAutoloadDump
    > @php artisan package:discover --ansi
    Discovered Package: awobaz/compoships
    Discovered Package: barryvdh/laravel-debugbar
    Discovered Package: facade/ignition
    Discovered Package: fideloper/proxy
    Discovered Package: fruitcake/laravel-cors
    Discovered Package: jenssegers/agent
    Discovered Package: kris/laravel-form-builder
    Discovered Package: laravel/fortify
    Discovered Package: laravel/jetstream
    Discovered Package: laravel/sanctum
    Discovered Package: laravel/tinker
    Discovered Package: laravelcollective/html
    Discovered Package: livewire/livewire
    Discovered Package: maatwebsite/excel
    Discovered Package: nesbot/carbon
    Discovered Package: nunomaduro/collision
    Discovered Package: staudenmeir/laravel-cte
    Discovered Package: yajra/laravel-datatables-buttons
    Discovered Package: yajra/laravel-datatables-editor
    Discovered Package: yajra/laravel-datatables-fractal
    Discovered Package: yajra/laravel-datatables-html
    Discovered Package: yajra/laravel-datatables-oracle
    Package manifest generated successfully.
    95 packages you are using are looking for funding.
    Use the `composer fund` command to find out more!
    > Illuminate\Foundation\ComposerScripts::postUpdate
    > @php artisan ide-helper:generate
    
       TypeError 
    
      Argument 3 passed to Kris\LaravelFormBuilder\FormHelper::__construct() must be of the type array, null given, called in /Users/[my project path]/vendor/kris/laravel-form-builder/src/Kris/LaravelFormBuilder/FormBuilderServiceProvider.php on line 65
    
      at vendor/kris/laravel-form-builder/src/Kris/LaravelFormBuilder/FormHelper.php:97
         93▕      * @param View    $view
         94▕      * @param Translator $translator
         95▕      * @param array   $config
         96▕      */
      ➜  97▕     public function __construct(View $view, Translator $translator, array $config = [])
         98▕     {
         99▕         $this->view = $view;
        100▕         $this->translator = $translator;
        101▕         $this->config = $config;
    
          +36 vendor frames 
      37  artisan:37
          Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
    Script @php artisan ide-helper:generate handling the post-update-cmd event returned with error code 1
    
    

    composer.json

    
        "scripts": {
            "post-autoload-dump": [
                "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
                "@php artisan package:discover --ansi"
            ],
            "post-root-package-install": [
                "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
            ],
            "post-create-project-cmd": [
                "@php artisan key:generate --ansi"
            ],
            "post-update-cmd": [
                "Illuminate\\Foundation\\ComposerScripts::postUpdate",
                "@php artisan ide-helper:generate",
                "@php artisan ide-helper:meta",
                "@php artisan ide-helper:models --dir=\"app/Models\" --write-mixin"
            ]
        }
    

    Edit: I solved it like this.

    1. I created the config file named config/laravel-form-builder.php
    2. I added the settings here to the file. config.php

    reference

    opened by mertasan 3
  • Array to string conversion error

    Array to string conversion error

    I've been looking at examples such as: https://github.com/kristijanhusak/laravel-form-builder/issues/176

    I have the child form showing on the main form, but when submitting it complains of an array to string conversion. I can see my sub form is an array of data. Do I need to handle the processing of this separately in the controller? What is the best way to test/extract for child models, so I can have generic controller code.

    On my form I have something like this:

                            $related_model = $this->getModel()->mysql()->findOrFail($connector_id);
                            $this->add('Repository Details', 'form', [
                                'class' => $this->getFormBuilder()->create(MySQLForm::class, ['model' => $related_model]),
                            ]);
                            break;
    

    Along with the other parent fields i.e.

                ->add('label', 'text', [
                    'label' => 'Label',
                    'rules' => 'required',
                ])
    

    The edit and controller code is generic:

    
      public function edit($id, FormBuilder $formBuilder)
        {
            $model = $this->model->findOrFail($id);
    
    
            $form = $formBuilder->create(get_class($this->form), [
                'method' => 'PUT',
                'model' => $model,
                'data' => $model->toArray(),
                'url' => route($this->route . '.update', $id)
            ])->remove('save');
    
            return view($this->bladePath . '.edit', compact('form'))->with(['path' => $this->path, 'links' => $this->links, 'model' => $model, 'metadata' => $this->metadata, 'bladePath' => $this->bladePath, 'route' => $this->route, 'form_booleans' => $this->form_booleans]);
        }
    
    
        public function update(Request $request, $id)
        {
            $model = $this->model->findOrFail($id);
            $form = $this->formBuilder->create(get_class($this->form), [
                'model' => $model,
                'data' => $model->toArray(),
            ]);
            
            if (!$form->isValid()) {
                return redirect()->back()->withErrors($form->getErrors())->withInput($request->except('_token'));
            }
            $model->update($request->except('_token', '_method'));
    
            return Redirect::route($this->route . '.show', $id)->with('alert-success', 'Successfully updated');
        }
    
    
    opened by adam-devapp 7
  • Getting the value of a field when rendering.

    Getting the value of a field when rendering.

    Hi,

    I was wondering if it is possible to get the value of a field when rendering, I have a custom template rendering my child forms, but depending on what the value of one of the fields in the child form is the wrapper class needs to change, but I am not sure how to get the values?

    Thank you

    help wanted 
    opened by Nardusgc 1
  • Missing Laravel 8 tag

    Missing Laravel 8 tag

    Missing Laravel 8 tag @see dev-master composer.json

    opened by sgc-fireball 5
  • update packagist / force dev to packagist or do proper release

    update packagist / force dev to packagist or do proper release

    1.30.0 does not work with Laravel 8

    kris/laravel-form-builder 1.30.0 requires illuminate/validation 5.6.*@dev|^6|^7

    opened by nekromoff 1
  • Regex Rules aren't supported anymore

    Regex Rules aren't supported anymore

    ErrorException: preg_match(): No ending delimiter '/' found - the exception is thrown when a regex with '|' is used, even if rules are declared separately in array

    opened by jelaucv 1
  • how i can use this in visual designer?

    how i can use this in visual designer?

    hey. i can build form designer with vue.js . do i can use this package with vue form designer ?

    opened by vahidalvandi 1
Releases(1.40.0)
Awes.io // boilerplate based on Vue, Nuxt, TailwindCSS plus Laravel as a backend. 🤟

Platform for Interactive Business Applications 10x faster to create than the traditional way • 3x increase application experiences • 60% decrease in d

Awes.io 640 Jun 15, 2021
Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be.

VatCalculator Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be. Integrates with Laravel and Cashier — or in a st

Dries Vints 932 Jun 15, 2021
Please see the Diglactic fork.

Update: 18 October 2020 There is now an official fork of Laravel Breadcrumbs: https://github.com/diglactic/laravel-breadcrumbs Blog post: https://news

Dave James Miller 2.4k Jun 17, 2021
Inertia.js Events for Laravel Dusk

Inertia.js Events for Laravel Dusk Requirements PHP 7.4+ Vue Laravel 8.0 and higher Support We proudly support the community by developing Laravel pac

Protone Media 9 Jun 14, 2021
dcat laravel-admin extension for china distpicker

dcat-admin extension Distpicker是一个中国省市区三级联动选择组件,这个包是基于Distpicker的dcat-admin扩展,用来将Distpicker集成进dcat-admin的表单中. 此扩展参考与引用: dcat-admin-extensions-distpick

mu 3 May 6, 2021
Laravel Livewire form component with declarative Bootstrap 5 fields and buttons.

Laravel Livewire Forms Laravel Livewire form component with declarative Bootstrap 5 fields and buttons. Requirements Bootstrap 5 Installation composer

null 24 Jun 10, 2021
Captcha for Laravel 5/6/7/8

Captcha for Laravel 5/6/7 A simple Laravel 5/6 service provider for including the Captcha for Laravel. for Laravel 4 Captcha for Laravel Laravel 4 Pre

MeWebStudio - Muharrem ERİN 1.9k Jun 15, 2021
Easy creation of slugs for your Eloquent models in Laravel

Eloquent-Sluggable Easy creation of slugs for your Eloquent models in Laravel. NOTE: These instructions are for the latest version of Laravel. If you

Colin Viebrock 3.2k Jun 14, 2021
Dead simple Laravel backend support for FilePond js.

Laravel FilePond Backend This package provides a straight forward backend support for Laravel application to work with FilePond file upload javascript

rahulhaque 6 May 28, 2021
A sample application with a multistep form built with Livewire.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

David Grzyb 5 Jun 2, 2021
jQuery DataTables API for Laravel 4|5|6|7|8

jQuery DataTables API for Laravel 4|5|6|7|8 This package is created to handle server-side works of DataTables jQuery Plugin via AJAX option by using E

Arjay Angeles 3.9k Jun 14, 2021
Automatically validating Eloquent models for Laravel

Validating, a validation trait for Laravel Validating is a trait for Laravel Eloquent models which ensures that models meet their validation criteria

Dwight Watson 918 Jun 8, 2021
A web installer for Laravel

Laravel Web Installer | A Web Installer Package About Requirements Installation Routes Usage Contributing Help Screenshots License About Do you want y

Rachid Laasri 1.7k Jun 13, 2021
laravel package for the Ar-PHP Project

laravel package for the Ar-PHP Project this is just a wrapper to use with laravel for the Ar-PHP Library, for more details checkout khaled-alshamaa

ATM-code 4 May 14, 2021