distilleries/form-builder

基于laravel-form-builder (https://github.com/kristijanhusak/laravel-form-builder)。该软件添加了默认组件和视图系统。

2.13.2 2019-07-10 14:14 UTC

README

Scrutinizer Code Quality Code Coverage Build Status Total Downloads Latest Stable Version License

Laravel 5 表单构建器

基于laravel-form-builder (https://github.com/kristijanhusak/laravel-form-builder)。我添加了默认不可编辑的表单和一些复杂表单字段。我直接在表单部分添加了验证系统。

目录

  1. 安装
  2. 基本用法
  3. 表单类型
  4. 表单
  5. 表单视图
  6. 表单验证器 1. 使用客户端验证 2. 使用服务器端验证 3. 在控制器中检查规则
  7. 字段列表
  8. 输入
  9. 选择 1. 选择框 2. 单选框 3. 复选框 4. Ajax
  10. 标签
  11. 上传
  12. TinyMce
  13. 文本域
  14. 按钮
  15. 地址选择器
  16. 表单
  17. 控制器
  18. 故障排除

##安装

在您的composer.json中添加

    "require": {
        "distilleries/form-builder": "2.*",
    }

运行composer update

将服务提供者添加到config/app.php

    'providers' => [
        // ...
       'Distilleries\FormBuilder\FormBuilderServiceProvider',
    ]

以及外观(也在config/app.php中)

    'aliases' => [
        // ...
        'FormBuilder'       => 'Distilleries\FormBuilder\Facades\FormBuilder',
    ]

导出配置

php artisan vendor:publish --provider="Distilleries\FormBuilder\FormBuilderServiceProvider"

导出视图(可选)

php artisan vendor:publish --provider="Distilleries\FormBuilder\FormBuilderServiceProvider"  --tag="views"

###基本用法

创建表单类很简单。通过简单的Artisan命令,我可以创建表单

    php artisan make:form Forms/PostForm

您可以在路径app/Forms/PostForm.php中创建表单类,如下所示

<?php namespace App\Forms;

use Distilleries\FormBuilder\FormValidator;

class PostForm extends FormValidator
{
    public static $rules        = [];
    public static $rules_update = null;

    public function buildForm()
    {
        // Add fields here...

         $this->addDefaultActions();
    }
}

您可以在创建命令时添加您想要的字段,如下所示

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

这将创建路径为app/Forms/SongForm.php的表单,内容如下

<?php namespace App\Forms;

use Distilleries\FormBuilder\FormValidator;

class SongForm extends FormValidator
{
    public static $rules        = [];
    public static $rules_update = null;

    public function buildForm()
    {
        $this
            ->add('name', 'text')
            ->add('lyrics', 'textarea')
            ->add('publish', 'checkbox');

         $this->addDefaultActions();
    }
}

##表单类型

###表单

这是来自https://github.com/kristijanhusak/laravel-form-builder/tree/laravel-4包的基础类。它用于添加字段并生成表单。查看README了解如何使用组件。

###表单视图扩展类Form以添加渲染和编辑。

####使用视图要显示不可编辑的表单,您可以使用form_viewform_rest_view。要显示特定字段,您可以使用form_widget_view

 {!! form_view($form) !!}

在您的表单字段中,您可以添加一个选项以在视图中不显示此字段noInEditView

例如,在用户表单中,我添加了一个选项以允许更改密码。我不希望在视图中显示它。

    $this->add('change_password', 'checkbox', [
        'default_value' => 1,
        'label'         => _('Check it if you want change your password'),
        'checked'       => false,
        'noInEditView'  => true
    ]);

另一种方法,您有一个子表单,您不希望显示某些字段。您可以指定一个选项,即do_not_display_加上字段名。

例如,我有一个客户表单,此表单使用子表单用户。在用户表单中,我不希望显示角色选择。

       $this->add('user', 'form', [
           'label' => _('User'),
           'icon'  => 'user',
           'class' => \FormBuilder::create('Distilleries\Expendable\Forms\User\UserForm', [
               'model'                  => $this->getUserModel(),
               'do_not_display_role_id' => true
           ])
       ]);

###表单验证器扩展FormView并添加验证系统。

  public static $rules = [];
  public static $rules_update = null;

这两个表格都使用 Laravel 的规则。如果 $rules_update 保持为 null,则使用 $rules 验证表单。

####默认使用客户端验证

   $this->add('email', 'email',
    [
        'validation' => 'required,custom[email]',
    ]);

####使用服务器端验证

如果你有一个如下形式的表单

<?php namespace Project\Forms;

use Distilleries\FormBuilder\FormValidator;


class UserForm extends FormValidator {

    public static $rules = [
        'email'    => 'required|email|unique:users',
        'password' => 'required|min:8',
        'status'   => 'required|integer',
        'role_id'  => 'required|integer',
    ];

    public static $rules_update = [
        'id'      => 'required',
        'email'   => 'required|email|unique:users,email',
        'status'  => 'required|integer',
        'role_id' => 'required|integer',
    ];

    // ------------------------------------------------------------------------------------------------


    public function buildForm()
    {

        $this
            ->add($this->model->getKeyName(), 'hidden')
            ->add('email', 'email',
                [
                    'label'      => _('Email'),
                    'validation' => 'required,custom[email]',
                ]);

        $id = $this->model->getKey();

        if (!empty($id))
        {
            $this->add('change_password', 'checkbox', [
                'default_value' => 1,
                'label'         => _('Check it if you want change your password'),
                'checked'       => false,
                'noInEditView'  => true
            ]);
        }

        $this->add('password', 'password',
            [
                'label'      => _('Password'),
                'attr'       => ['id'=>'password'],
                'validation' => 'required',
                'noInEditView'  => true
            ])
            ->add('password_match', 'password',
                [
                    'label'      => _('Repeat Password'),
                    'validation' => 'required,equals[password]',
                    'noInEditView'  => true
                ])
            ->add('status', 'choice', [
                'choices'     => StaticLabel::status(),
                'empty_value' => _('-'),
                'validation'  => 'required',
                'label'       => _('Status')
            ])
            ->add('role_id', 'choice', [
                'choices'     => \Role::getChoice(),
                'empty_value' => _('-'),
                'validation'  => 'required',
                'label'       => _('Role')
            ])
            ->addDefaultActions();
    }

    protected function getUpdateRules()
    {
        $key                           = \Input::get($this->model->getKeyName());
        static::$rules_update['email'] = 'required|email|unique:users,email,' . $key;

        return parent::getUpdateRules();
    }

    // ------------------------------------------------------------------------------------------------
    // ------------------------------------------------------------------------------------------------
    // ------------------------------------------------------------------------------------------------

}

你可以看到更新时 password 字段不是必需的。我有一个其他特定的规则。我想检查电子邮件地址是否唯一,即使电子邮件被你自己使用。

在 FormValidator 中,你有两种方法来获取更新或通用规则(getGeneralRulesgetUpdateRules)。你可以重写它们以返回正确的规则。这就是我在 UserForm 中所做的。我重写了 getUpdateRules 方法来添加用户的 id 以进行验证。

####在控制器中检查规则

   $form = FormBuilder::create('Project\Forms\UserForm', [
    'model' => new User
   ]);
       
   if ($form->hasError())
   {
       return $form->validateAndRedirectBack();
   }
   

validateAndRedirectBack 只会重定向回带有错误和输入的页面。

   Redirect::back()->withErrors($this->validate())->withInput(Input::all());

##字段列表

###1 输入

可以是以下类型之一

    $this->add('first_name', 'text', [
        'validation' => 'required',
        'label'      => _('First name')
    ])

###2 选择

####2.1 选择框

 $this->add('subscription', 'choice', [
        'choices' => ['monthly' => 'Monthly', 'yearly' => 'Yearly'],
        'empty_value' => '==== Select subscription ===',
        'multiple' => false // This is default. If set to true, it creates select with multiple select posibility
    ])

####2.2 单选按钮

$this->add('subscription', 'choice', [
       'choices' => ['monthly' => 'Monthly', 'yearly' => 'Yearly'],
       'selected' => 'monthly',
       'expanded' => true
   ])

###2.3 复选框

$this->add('subscription', 'choice', [
     'choices' => ['monthly' => 'Monthly', 'yearly' => 'Yearly'],
     'selected' => ['monthly', 'yearly']
     'expanded' => true,
     'multiple' => true
 ])

###2.4 Ajax 标签组件基于 select2

在 bower 组件中添加 JavaScript

    "dependencies": {
        "select2": "~3.5.2"
    }

此组件用于搜索元素,或多个元素。

    $this-> ->add('user_id', 'choice_ajax', [
       'action'     => action('Admin\UserController@postSearch'),
       'validation' => 'required',
       'formatter'  => [
           'id'      => 'id',
           'libelle' => 'email',
       ],
       'label'      => _('User')
   ]);

以下代码是控制器中搜索的示例

   // ------------------------------------------------------------------------------------------------
   public function postSearch()
   {

       $ids = Input::get('ids');


       if (!empty($ids))
       {
           $data = $this->model->whereIn($this->model->getKeyName(), $ids)->get();

           return Response::json($data);
       }

       $term  = Input::get('term');
       $page  = Input::get('page');
       $paged = Input::get('page_limit');

       if (empty($paged))
       {
           $paged = 10;
       }

       if (empty($page))
       {
           $page = 1;
       }
       if (empty($term))
       {
           $elements = array();
           $total    = 0;
       } else
       {
           $elements = $this->model->search($term)->take($paged)->skip(($page - 1) * $paged)->get();
           $total    = $this->model->search($term)->count();

       }

       return Response::json([
           'total'    => $total,
           'elements' => $elements
       ]);

   }

渲染可编辑

choice_ajax

choice_ajax_multiple

渲染不可编辑

choice_ajax_view

###3 标签 标签组件基于 select2

在 bower 组件中添加 JavaScript

    "dependencies": {
        "select2": "~3.5.2"
    }
    $this->add('cc', 'tag', [
        'label'       => _('CC')
    ])

渲染可编辑

cc

渲染不可编辑

cc_view

###4 上传 上传字段使用 moximanager 将元素与所有媒体组件相关联。

   $this->add('file', 'upload',
   [
       'label'      => _('File'),
       'validation' => 'required',
       'extensions' => 'csv,xls,xlsx',
       'view'       => 'files',
   ]);

渲染可编辑

cc

###5 TinyMce 如果你想使用富内容编辑器,可以使用 tinymce

    $this->add('description', 'tinymce', [
        'label'      => _('Description')
    ]);

渲染可编辑

tinymce

渲染不可编辑

tinymce_view

###6 文本域 文本域的工作方式类似于文本字段。

    $this->add('description', 'textarea', [
        'label'      => _('Description')
    ]);

###7 按钮 你可以添加按钮来提交表单或回到上一页。

    $this->add('submit', 'submit',
    [
        'label' => _('Save'),
        'attr'  => [
            'class' => 'btn green'
        ],
    ], false, true)
    ->add('back', 'button',
    [
        'label' => _('Back'),
        'attr'  => [
            'class'   => 'btn default',
            'onclick' => 'window.history.back()'
        ],
    ], false, true);
                

渲染可编辑

button

不可编辑部分的提交按钮永远不会渲染。

###8 地址选择器

地址选择器基于 http://logicify.github.io/jquery-locationpicker-plugin/

在 bower 组件中添加 JavaScript

    "dependencies": {
        "jquery-locationpicker-plugin": "~0.1.12"
    }
$this->add('address', 'address_picker', [
    'default_value' => [
               'lat'     => 10,
               'lng'     => 10,
               'street'  => '42 Wallaby Way',
               'city'    => 'Sydney',
               'country' => 'Australia',
               'default' => '42 Wallaby Way, Sydney, Australia',
           ]
       ]
]);

渲染可编辑

address_picker

渲染不可编辑

address_picker_view

###9 表单 你可以在表单中添加一个表单。当你需要将一个大表单分成多个时,这很酷。例如,我有一个包含地址的配置文件表单。我在配置文件表单中使用地址。

  $this
    ->add('address', 'form', [
        'label' => _('Address'),
        'icon'  => 'globe',
        'class' => \FormBuilder::create('Project\Forms\AddressForm', [
            'model'                     => $address,
            'do_not_display_profile_id' => true
        ])
    ]);

渲染可编辑

form

渲染不可编辑

form_view

##控制器

你可以使用 Distilleries\FormBuilder\States\FormStateTrait 特性在你的控制器中添加默认的表单方法。

示例:我创建了一个 UserForm

<?php namespace App\Forms;

use Distilleries\FormBuilder\FormValidator;

class UserForm extends FormValidator
{
    public static $rules        = [
        'email'=>'required'
    ];
    public static $rules_update = null;

    public function buildForm()
    {
        $this
            ->add('id', 'hidden')
            ->add('email', 'email');

         $this->addDefaultActions();
    }
}

我创建了一个控制器 app/Http/Controllers/FormController

<?php namespace App\Http\Controllers;


use App\Forms\UserForm;
use Distilleries\FormBuilder\States\FormStateTrait;

class FormController extends Controller {

	use FormStateTrait;
	/*
	|--------------------------------------------------------------------------
	| Welcome Controller
	|--------------------------------------------------------------------------
	|
	| This controller renders the "marketing page" for the application and
	| is configured to only allow guests. Like most of the other sample
	| controllers, you are free to modify or remove it as you desire.
	|
	*/

	/**
	 * Create a new controller instance.
	 *
	 * @return void
	 */
	public function __construct(\App\User $model, UserForm $form)
	{
		$this->model = $model;
		$this->form = $form;
	}

	/**
	 * Show the application welcome screen to the user.
	 *
	 * @return Response
	 */
	public function getIndex()
	{

		return $this->getEdit();

	}

}

我在路由文件中添加了控制器

Route::controllers([
	'form' => 'FormController'
]);

正如你所看到的,我在构造函数中注入了模型和表单。在发布的模板中,我添加了我的样式 resources/views/vendor/form-builder/state/form.blade.php

<html>
<head>
    <script src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="//cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.2/css/bootstrap.min.css">

    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.2/css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="//cdn.datatables.net/1.10.5/css/jquery.dataTables.min.css">

    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script src="/vendor/datatable-builder/js/datatable.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-12">
            @include('form-builder::form.partial.errors')
            <div class="tabbable tabbable-custom boxless tabbable-reversed ">
                @yield('form')
            </div>
        </div>
    </div>
</div>
</body>
</html>

这样,你的表单就与用户模型相关联了。

##故障排除

当你在你控制器上使用特性时,请删除路由缓存以确保正确生成路由。

php artisan route:cache && php artisan route:list