├── .gitignore ├── DEMO.md ├── LICENSE ├── README.md ├── composer.json ├── resources ├── assets │ └── table.css └── views │ ├── display │ ├── div.blade.php │ └── table.blade.php │ ├── error.blade.php │ ├── field │ └── show.blade.php │ └── table.blade.php └── src ├── Field ├── Collect.php ├── CollectValidator.php ├── Show.php └── TextSmall.php ├── FromTable.php ├── RowTableServiceProvider.php ├── Table.php ├── TableExtension.php └── TableRow.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.phar 3 | /vendor 4 | composer.phar 5 | composer.lock 6 | *.project 7 | .idea/ -------------------------------------------------------------------------------- /DEMO.md: -------------------------------------------------------------------------------- 1 | ```php 2 | /** 3 | * Make a form builder. 4 | * 5 | * @return Form 6 | */ 7 | protected function form() 8 | { 9 | /** 10 | * textSmall => \Ichynul\RowTable\Field\TextSmall::class 11 | * show => \Ichynul\RowTable\Field\Show::class 12 | * 13 | **************************************************************************************************** 14 | * $tableRow-element($column, $label, $width); //div时 [useDiv(true)] class="col-sm-{$width}" 15 | * 16 | * $tableRow-element($column, $label, $colspan); // table 时 colspan="{$colspan}" 17 | * 18 | * $tableRow-show($html, $label, $width)->textAlign($align); //div时 [useDiv(true)] class="col-sm-{$width}" 19 | * 20 | * $tableRow-show($html, $label , $colspan)->textAlign($align)->textWidth($textWidth); //table 时 colspan="{$colspan}"; 21 | * 22 | * $tableRow-show($html, $label , $width)->addStyle('text-align', $align)->addStyle('width',$textWidth)->addStyle('anystyle','anyvalue'); 23 | */ 24 | 25 | $form = new Form(new User); 26 | 27 | $form->text('somerow', '混合使用form')->rules('required'); 28 | 29 | //$form->show("

************Demo 1 , 使用 table************

")->textWidth('100%')->textAlign('center'); 30 | // equals 31 | $form->show("

************Demo 1 , 使用 table************

")->addStyle('width', '100%')->addStyle('text-align', 'center'); 32 | 33 | $form->divide(); 34 | /*************************************/ 35 | 36 | $months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']; 37 | $names = ['小刚', '小明', '小红', '张三']; 38 | $headers1 = []; 39 | $tablerows = []; 40 | /*************************************/ 41 | $h = new Show('姓名\\月份'); 42 | $headers1[] = $h->textWidth('120px')->render(); 43 | 44 | $m = 0; 45 | foreach ($months as $month) { 46 | $m += 1; 47 | $h = new Show($month); 48 | $h->addStyle('background-color', $m % 3 == 0 ? 'green' : '#f1f1f1'); 49 | $headers1[] = $h->render(); 50 | } 51 | 52 | $tableRow = new TableRow(); 53 | $tableRow->show('小刚')->textWidth('120px'); 54 | 55 | $i = 0; 56 | $j = 0; 57 | 58 | foreach ($names as $name) { 59 | $row = new TableRow(); 60 | $i += 1; 61 | $row->show($name)->addStyle('color', $i % 2 == 0 ? 'blue' : 'orange'); 62 | foreach ($months as $month) { 63 | $j += 1; 64 | $row->textSmall("table_1_{$i}_{$j}", $month . '工资')->rules(($i * $j) % 10 == 0 ? 'min:3' : ''); 65 | } 66 | $tablerows[] = $row; 67 | } 68 | 69 | $form->rowtable('工资情况') 70 | ->setHeaders($headers1) 71 | ->setRows($tablerows); 72 | 73 | /*************************************/ 74 | 75 | $form->show("

************Demo 2 , 使用 div************

")->textWidth('100%')->textAlign('center')->addStyle('color', 'red'); 76 | 77 | $form->icon('somerow2', '中间混合使用form')->rules('required'); 78 | 79 | $form->divide(); 80 | 81 | $i = 0; 82 | $j = 0; 83 | 84 | foreach ($names as $name) { 85 | $i += 1; 86 | $row = new TableRow(); 87 | foreach ($months as $month) { 88 | $j += 1; 89 | if ($i % 3 == 0) { 90 | $row->checkbox("table_2_{$i}_{$j}", $month . '工资', 6) //radio 比较占地方 col-sm-6,每行2列 91 | ->options(['3000' => '¥3000', '4000' => '¥4000', '8000' => '¥8000']); 92 | } else if ($i % 4 == 0) { 93 | $row->select("table_2_{$i}_{$j}", $month . '工资', 4) //col-sm-4,每行3列 94 | ->rules(($i * $j) % 7 == 0 ? 'int:max10000' : '') 95 | ->options(['3000' => '¥3000', '4000' => '¥4000', '8000' => '¥8000'])->setWidth(7, 4); //手动设置一下 label和 select 宽带 96 | } else { 97 | $row->text("table_2_{$i}_{$j}", $month . '工资') //col-sm-3,每行4列 , 未设置 且 cols > 4 ,自适应 每行4列 98 | ->rules(($i * $j) % 8 == 0 ? 'required' : ''); 99 | } 100 | } 101 | $form->rowtable($name . '工资') 102 | ->setRows($row) 103 | ->useDiv(true); 104 | $form->divide(); 105 | } 106 | 107 | /*************************************/ 108 | $form->show("

************Demo 3 , use div build a user center ************

")->textWidth('100%')->textAlign('center'); 109 | 110 | $userRow = new TableRow(); 111 | $userRow->image('photo', '头像', 6)->value('/vendor/laravel-admin/AdminLTE/dist/img/default-50x50.gif')->removeable(); 112 | $userRow->html('没个性也签名~', '个性签名', 6); 113 | 114 | $userRow1 = new TableRow(); 115 | $userRow1->text('name', '姓名', 6)->rules('required'); 116 | $userRow1->radio('gender', '性别', 6)->options(['0' => '保密', '1' => '男', '2' => '女']); 117 | 118 | $userRow2 = new TableRow(); 119 | $userRow2->number('age', '年龄', 6)->max(99)->min(18); 120 | $userRow2->date('birthday', '生日', 6)->rules('required'); 121 | 122 | $userRow2->textarea('about', '个人简介', 12)->setWidth(10, 2); //独占一行,因为其他行有两列 123 | 124 | $form->rowtable('个人中心', '11') 125 | ->setRows([$userRow, $userRow1, $userRow2]) 126 | ->useDiv(true); 127 | 128 | $form->divide(); 129 | /*************************************/ 130 | $form->show("

************Demo 4 , use table build a user center ************

")->textWidth('100%')->textAlign('center'); 131 | 132 | //这个比较麻烦,仅作为演示 133 | /*********************/ 134 | 135 | $form->rowtable('Using colspan', function ($table) { 136 | $table->row(function (TableRow $row) { 137 | $row->show('头像')->textAlign('left'); 138 | $row->show('个性签名')->textAlign('left'); 139 | }); 140 | 141 | $table->row(function (TableRow $row) { 142 | $row->image('photo')->default('/vendor/laravel-admin/AdminLTE/dist/img/default-50x50.gif'); 143 | $row->show('没个性也签名~')->textAlign('left'); 144 | }); 145 | 146 | $table->row(function (TableRow $row) { 147 | $row->show('姓名')->textAlign('left')->addStyle('color', 'red'); 148 | $row->show('性别')->textAlign('left')->addStyle('color', 'blue')->addStyle('font-size', '18px'); // add styles 149 | }); 150 | 151 | $table->row(function (TableRow $row) { 152 | $row->text('name'); 153 | $row->radio('gender')->options(['0' => '保密', '1' => '男', '2' => '女']); 154 | }); 155 | 156 | $table->row(function (TableRow $row) { 157 | $row->show('年龄')->textAlign('left')->addStyle('color', 'red'); 158 | $row->show('生日')->textAlign('left'); 159 | }); 160 | 161 | $table->row(function (TableRow $row) { 162 | $row->number('age', '年龄')->max(99)->min(18); 163 | $row->date('birthday', '生日'); 164 | }); 165 | 166 | $table->row(function (TableRow $row) { 167 | $row->show('个人简介', 2)->textAlign('left'); // colspan=2 168 | }); 169 | 170 | $table->row(function (TableRow $row) { 171 | $row->textarea('about', 2); // colspan=2 172 | }); 173 | }); 174 | 175 | $form->divide(); 176 | /*************************************/ 177 | $form->show("

************Demo 5 , table colspan, ************

")->textWidth('100%')->textAlign('center'); 178 | 179 | $form->rowtable('Using colspan', function ($table) { 180 | $table->row(function (TableRow $row) { 181 | $row->text('row1'); //defautt 1 182 | $row->text('row2'); 183 | $row->text('row3')->rules('required'); 184 | $row->text('row4'); 185 | }); 186 | 187 | $table->row(function (TableRow $row) { 188 | $row->text('row5', 2); 189 | $row->text('row6', 2); 190 | }); 191 | 192 | $table->row(function (TableRow $row) { 193 | $row->text('row7', 2); 194 | $row->text('row8'); //defautt 1 195 | $row->text('row8', 1)->rules('required'); 196 | }); 197 | 198 | $table->row(function (TableRow $row) { 199 | $row->text('row9', 1); 200 | $row->text('row10', 2)->rules('required'); 201 | $row->text('row11', 1); 202 | }); 203 | }); 204 | 205 | $form->divide(); 206 | /*************************************/ 207 | 208 | 209 | $form->display('created_at', trans('admin.created_at')); 210 | $form->display('updated_at', trans('admin.updated_at')); 211 | 212 | return $form; 213 | } 214 | ``` 215 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jens Segers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-admin row-table 2 | 3 | ## Installation 4 | 5 | Run : 6 | 7 | ``` 8 | $ composer require ichynul/row-table 9 | ``` 10 | 11 | Then run: 12 | 13 | ``` 14 | $ php artisan vendor:publish --tag=row-table 15 | 16 | ``` 17 | 18 | ##### 19 | ##### 推荐使用 $field->setGroupClass('col-md-6');//这样的方式来实现栅格布局,毕竟官方的兼容性更好一些。 20 | ##### It is recommended to use $field->setgroupclass('col-md-6'); // this official way to achieve grid layout. 21 | 22 | ## Usage 23 | 24 | ```php 25 | protected function form() 26 | { 27 | $form = new Form(new Task); 28 | 29 | $headers = ['备注', '服务费用', '服务评分']; 30 | $tableRow = new TableRow(); 31 | 32 | $tableRow->text('status', '任务状态')->options(Task::$statusMap)->attribute(['readonly' => 'readonly']); 33 | $tableRow->text('fee', '服务费用')->rules('required'); 34 | $tableRow->number('rating', '服务评分', 2)->max(5)->min(1);//这个表少了一列,这里设置colspan=2 ,其他可以不写默认1 35 | /*************************************/ 36 | $headers2 = ['地址', '评价', '图片']; 37 | $tableRow2 = new TableRow(); 38 | $tableRow2->text('address', '地址')->rules('required'); 39 | $tableRow2->text('comment', '评价'); 40 | $tableRow2->text('username', '姓名'); 41 | $tableRow2->text('viwe', '查看'); 42 | 43 | $form->rowtable('任务信息1') 44 | ->setHeaders($headers)//使用table时设置,div设置无效 45 | //->setRows($tableRow)//设置 一个row 46 | ->setRows([$tableRow, $tableRow2]) 47 | ->useDiv(true); //使用div显示,默认 table 48 | //->headersTh(true);//使用table时 头部使用,默认使用样式有些差别 49 | //->getTableWidget()//extends Encore\Admin\Widgets\Table 50 | //->offsetSet("style", "width:1000px;"); 51 | 52 | // 另外一种代码风格 Another code style 53 | $form->rowtable('任务信息2', function ($table) { 54 | $table->row(function (TableRow $row) { 55 | $row->text('text1', 'label1')->rules('required'); 56 | $row->text('text2', 'label2'); 57 | $row->text('text3', 'label3'); 58 | }); 59 | $table->row(function (TableRow $row) { 60 | $row->text('text4', 'label4'); 61 | $row->text('text5', 'label5'); 62 | $row->text('text6', 'label6'); 63 | }); 64 | $table->row(function (TableRow $row) { 65 | $row->text('text7', 'label7'); 66 | $row->text('text8', 'label8'); 67 | $row->text('text9', 'label9'); 68 | }); 69 | //$table->useDiv(false); 70 | //$table->setHeaders(['h1','h2']); 71 | //$table->useDiv(false); 72 | //$table->headersTh(true);//使用table时 头部使用,默认使用样式有些差别 73 | //$table->getTableWidget()//extends Encore\Admin\Widgets\Table 74 | //->offsetSet("style", "width:1000px;"); 75 | }); 76 | 77 | $form->textarea('remark', '备注')->rules('required'); 78 | $form->display('created_at', trans('admin.created_at')); 79 | $form->display('updated_at', trans('admin.updated_at')); 80 | 81 | /** 82 | * $tableRow-element($column, $label, $width); //div 时 class="col-sm-$width" 83 | * 84 | * $tableRow-element($column, $colspan); // table 时 colspan="$width" 85 | * 86 | * $element: 理论上可以是任何 form 元素 (不考虑布局效果) 87 | * 88 | * $width : 89 | * table模式 时 为 colspan="width" , 多行且每行元素数量不同时很有用 90 | * 91 | * div模式 时 为 class="col-sm-width" . 排列不下时自动换行 92 | * 93 | * div模式 若一个tableRow中所有元素都未设置 $width ,将会自适应 (columns >=4 每行4个并自动换行,小于4则全部在一行) 94 | */ 95 | 96 | return $form; 97 | } 98 | ``` 99 | 100 | License 101 | 102 | --- 103 | 104 | Licensed under [The MIT License (MIT)](LICENSE). 105 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ichynul/row-table", 3 | "description": "laravel-admin extension row-table", 4 | "type": "library", 5 | "keywords": ["laravel-admin", "extension"], 6 | "homepage": "https://github.com/ichynul/row-table", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "ichynul", 11 | "email": "ichynul@outlook.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=7.0.0", 16 | "encore/laravel-admin": "~1.6" 17 | }, 18 | "require-dev": { 19 | "phpunit/phpunit": "~6.0" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "Ichynul\\RowTable\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "Ichynul\\RowTable\\RowTableServiceProvider" 30 | ] 31 | 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/assets/table.css: -------------------------------------------------------------------------------- 1 | table.table-fields tbody tr td { 2 | border: none; 3 | padding-right: 10px; 4 | padding-top: 0; 5 | padding-bottom: 0; 6 | padding-left: 0; 7 | } 8 | 9 | table.table-fields thead tr td, 10 | table.table-fields thead tr th { 11 | padding: 8px 0; 12 | margin-bottom: 8px; 13 | height: 34px; 14 | } 15 | 16 | .table.table-fields { 17 | margin: 0; 18 | padding: 0; 19 | } 20 | 21 | table.table-fields .form-group.has-error .control-label, 22 | table.table-fields .form-group.has-error br, 23 | div.table-fields .form-group.has-error br { 24 | display: none; 25 | } 26 | 27 | .table-has-error .form-group.has-error .control-label { 28 | color: inherit; 29 | } 30 | 31 | .control-label.table-error { 32 | color: #dd4b39; 33 | } 34 | 35 | .form-group.has-error .select2-container .select2-selection { 36 | border-color: #dd4b39; 37 | box-shadow: none; 38 | } 39 | 40 | div.table-fields .form-group.has-error div .control-label { 41 | display: none; 42 | } 43 | 44 | div.table-fields .form-group .col-sm-12.control-label { 45 | margin-bottom: 10px; 46 | } 47 | 48 | div.table.table-fields td .form-group { 49 | margin-bottom: 7px 50 | } 51 | 52 | .table.table-fields .col-sm-12 .control-label { 53 | text-align: left; 54 | } 55 | 56 | .table.table-fields .show-text { 57 | vertical-align: middle; 58 | } 59 | -------------------------------------------------------------------------------- /resources/views/display/div.blade.php: -------------------------------------------------------------------------------- 1 |
2 | @foreach($rows as $row) 3 |
4 | @foreach($row->geFields() as $item) 5 |
{!! $item->render() !!}
6 | @endforeach 7 |
8 | @endforeach 9 |
-------------------------------------------------------------------------------- /resources/views/display/table.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @if(count($headers)) 3 | 4 | 5 | @foreach($headers as $header) 6 | @if($headers_th) 7 | 8 | @else 9 | 10 | @endif 11 | @endforeach 12 | 13 | 14 | @endif 15 | 16 | @foreach($rows as $row) 17 | 18 | @foreach($row->geFields() as $item) 19 | 20 | @endforeach 21 | 22 | @endforeach 23 | 24 |
{!! $header !!}{!! $header !!}
{!! $item->render() !!}
-------------------------------------------------------------------------------- /resources/views/error.blade.php: -------------------------------------------------------------------------------- 1 | @if(is_array($errorKey)) 2 | @foreach($errorKey as $key => $col) 3 | @if($errors->has($col.$key)) 4 | @foreach($errors->get($col.$key) as $message) 5 | 6 | @endforeach 7 | @endif 8 | @endforeach 9 | @else 10 | @if($errors->has($errorKey)) 11 | @foreach($errors->get($errorKey) as $message) 12 | 13 | @endforeach 14 | @endif 15 | @endif -------------------------------------------------------------------------------- /resources/views/field/show.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | {!! $value !!} 6 | 7 | @include('admin::form.help-block') 8 | 9 |
10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/views/table.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | {!! $table !!} 7 | 8 | @include('row-table::error') 9 | 10 | @include('admin::form.help-block') 11 | 12 |
13 |
-------------------------------------------------------------------------------- /src/Field/Collect.php: -------------------------------------------------------------------------------- 1 | fields; 27 | } 28 | 29 | /** 30 | * @param Field $field 31 | * 32 | * @return $this 33 | */ 34 | public function pushField(Field $field) 35 | { 36 | if (!$this->fields) { 37 | $this->fields = new Collection(); 38 | } 39 | 40 | $this->fields->push($field); 41 | 42 | return $this; 43 | } 44 | 45 | /** 46 | * Get specify field. 47 | * 48 | * @param string $name 49 | * 50 | * @return mixed 51 | */ 52 | public function field($name) 53 | { 54 | if (!$this->fields) { 55 | return null; 56 | } 57 | 58 | return $this->fields->first(function (Field $field) use ($name) { 59 | return $field->column() == $name; 60 | }); 61 | } 62 | 63 | /** 64 | * Get validation messages. 65 | * 66 | * @param array $input 67 | * 68 | * @return MessageBag|bool 69 | */ 70 | public function validationMessages($input, $errorKey, $label = '') 71 | { 72 | $rules = $messages = $labels = []; 73 | 74 | $this->fields->each(function ($field) use (&$rules, &$messages, &$labels, $input) { 75 | if (!$validator = $field->getValidator($input)) { 76 | return; 77 | } 78 | 79 | if (($validator instanceof Validator) && !$validator->passes()) { 80 | 81 | $err = $validator->errors()->first($field->getErrorKey()); 82 | 83 | $rules[$field->getErrorKey()] = Arr::get($validator->getRules(), $field->getErrorKey()); 84 | 85 | $messages[$field->getErrorKey() . '.required'] = $err; 86 | 87 | $labels[$field->getErrorKey()] = $field->label(); 88 | } 89 | }); 90 | 91 | if (empty($messages)) { 92 | return false; 93 | } 94 | 95 | $rules[$errorKey] = 'required'; 96 | $messages[$errorKey . '.required'] = implode(' ', array_values($messages)); 97 | $labels[$errorKey] = $label ?: $errorKey; 98 | 99 | return ValidatorTool::make($input, $rules, $messages, $labels); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Field/Show.php: -------------------------------------------------------------------------------- 1 | addStyle('text-align', $align); 36 | 37 | return $this; 38 | } 39 | 40 | /** 41 | * set text-align 42 | * 43 | * @param [strign] $align 44 | * @return $this 45 | */ 46 | public function textWidth($width) 47 | { 48 | $this->addStyle('width', $width); 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * set text-align 55 | * 56 | * @param [strign] $align 57 | * @return $this 58 | */ 59 | public function addStyle($key, $val) 60 | { 61 | $this->styles[$key] = $val; 62 | 63 | return $this; 64 | } 65 | 66 | /** 67 | * Create a new Show instance. 68 | * 69 | * @param mixed $text 70 | * @param array $arguments 71 | */ 72 | public function __construct($html, $arguments = []) 73 | { 74 | $this->html = $html; 75 | 76 | $this->width['field'] = Arr::get($arguments, 0, 12); 77 | 78 | $this->addStyle('width', 'auto'); 79 | 80 | $this->addStyle('text-align', 'center'); 81 | 82 | $this->addStyle('min-width', '70px'); 83 | } 84 | 85 | public function variables(): array 86 | { 87 | return array_merge($this->variables, [ 88 | 'help' => $this->help, 89 | 'class' => $this->getElementClassString(), 90 | 'value' => $this->html, 91 | 'viewClass' => $this->getViewElementClasses(), 92 | 'attributes' => $this->formatAttributes(), 93 | 'divsSyles' => $this->formatStyles(), 94 | ]); 95 | } 96 | 97 | /** 98 | * Format the field attributes. 99 | * 100 | * @return string 101 | */ 102 | protected function formatStyles() 103 | { 104 | $html = []; 105 | 106 | foreach ($this->styles as $name => $value) { 107 | $html[] = $name . ': ' . $value; 108 | } 109 | 110 | return implode(' ;', $html); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Field/TextSmall.php: -------------------------------------------------------------------------------- 1 | initPlainInput(); 20 | 21 | $this->setLabelClass(['hidden'])->attribute(['title' => $this->label()]); 22 | 23 | $this 24 | ->defaultAttribute('type', 'text') 25 | ->defaultAttribute('style', 'text-align:center;font-size:12px;') 26 | ->defaultAttribute('id', $this->id) 27 | ->defaultAttribute('name', $this->elementName ? : $this->formatName($this->column)) 28 | ->defaultAttribute('value', old($this->column, $this->value())) 29 | ->defaultAttribute('class', 'form-control ' . $this->getElementClassString()) 30 | ->defaultAttribute('placeholder', $this->getPlaceholder()); 31 | 32 | $this->setWidth(12, 0); 33 | 34 | $this->addVariables([ 35 | 'prepend' => false, 36 | 'append' => false, 37 | ]); 38 | 39 | return parent::render(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/FromTable.php: -------------------------------------------------------------------------------- 1 | useDiv = $div == true; 29 | 30 | return $this; 31 | } 32 | 33 | /** 34 | * Set table whether th headers. 35 | * 36 | * @param boolean $th 37 | * 38 | * @return $this 39 | */ 40 | public function headersTh($th = true) 41 | { 42 | $this->headers_th = $th == true; 43 | 44 | return $this; 45 | } 46 | 47 | /** 48 | * whether using div 49 | * 50 | * @return bollean 51 | */ 52 | public function usingDiv() 53 | { 54 | return $this->useDiv; 55 | } 56 | 57 | /** 58 | * whether using div 59 | * 60 | * @return bollean 61 | */ 62 | public function usingHeadsTh() 63 | { 64 | return $this->heads_th; 65 | } 66 | 67 | public function render() 68 | { 69 | if ($this->usingDiv()) { 70 | 71 | $this->view = 'row-table::display.div'; 72 | 73 | } else { 74 | 75 | $this->view = 'row-table::display.table'; 76 | } 77 | 78 | $vars = [ 79 | 'headers' => $this->headers, 80 | 'rows' => $this->rows, 81 | 'style' => $this->style, 82 | 'attributes' => $this->formatAttributes(), 83 | 'headers_th' => $this->headers_th 84 | ]; 85 | 86 | return view($this->view, $vars)->render(); 87 | } 88 | } -------------------------------------------------------------------------------- /src/RowTableServiceProvider.php: -------------------------------------------------------------------------------- 1 | views()) { 21 | 22 | $this->loadViewsFrom($views, $extension->name); 23 | } 24 | 25 | if ($this->app->runningInConsole() && $assets = $extension->assets()) { 26 | 27 | $this->publishes( 28 | [$assets => public_path('vendor/laravel-admin-ext/row-table')], 29 | 'row-table' 30 | ); 31 | } 32 | 33 | Admin::booting(function () { 34 | 35 | Form::extend('rowtable', Table::class); 36 | 37 | Form::extend('textSmall', \Ichynul\RowTable\Field\TextSmall::class); 38 | 39 | Form::extend('show', \Ichynul\RowTable\Field\Show::class); 40 | }); 41 | } 42 | } -------------------------------------------------------------------------------- /src/Table.php: -------------------------------------------------------------------------------- 1 | label = $label; 48 | 49 | $this->column = '__tabel__'; 50 | 51 | $this->fromTable = new FromTable([], []); 52 | 53 | $this->fromTable->class($this->defaultClass); 54 | 55 | $func = Arr::get($arguments, 0, null); 56 | 57 | if ($func && $func instanceof Closure) { 58 | 59 | call_user_func($func, $this); 60 | } 61 | } 62 | 63 | /** 64 | * Call submitted callback. 65 | * 66 | * @return mixed 67 | */ 68 | protected function bindSubmitted() 69 | { 70 | $this->form->submitted(function (Form $form) { 71 | 72 | $this->form->ignore($this->column); 73 | 74 | foreach ($this->rows as $row) { 75 | 76 | foreach ($row->geFields() as $field) { 77 | 78 | $this->form->builder()->fields()->push($field); 79 | } 80 | } 81 | }); 82 | } 83 | 84 | /** 85 | * Set useDiv 86 | * 87 | * @param boolean $useDiv 88 | * 89 | * @return $this 90 | */ 91 | public function useDiv($div = true) 92 | { 93 | $this->fromTable->useDiv($div); 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * Set table whether th headers. 100 | * 101 | * @param boolean $th 102 | * 103 | * @return $this 104 | */ 105 | public function headersTh($th = true) 106 | { 107 | $this->fromTable->headersTh($th); 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * Set table headers. 114 | * 115 | * @param array $headers 116 | * 117 | * @return $this 118 | */ 119 | public function setHeaders($headers = []) 120 | { 121 | $this->fromTable->setHeaders($headers); 122 | 123 | return $this; 124 | } 125 | 126 | /** 127 | * @param Form $form 128 | * 129 | * @return $this 130 | */ 131 | 132 | public function setForm(Form $form = null) 133 | { 134 | parent::setForm($form); 135 | 136 | foreach ($this->rows as $row) { 137 | 138 | foreach ($row->geFields() as $field) { 139 | $field->setForm($form); 140 | } 141 | } 142 | 143 | $this->bindSubmitted(); 144 | 145 | return $this; 146 | } 147 | 148 | /** 149 | * Set Widget/Form as field parent. 150 | * 151 | * @param WidgetForm $form 152 | * 153 | * @return $this 154 | */ 155 | public function setWidgetForm(WidgetForm $form) 156 | { 157 | parent::setWidgetForm($form); 158 | 159 | foreach ($this->rows as $row) { 160 | 161 | foreach ($row->geFields() as $field) { 162 | $field->setWidgetForm($form); 163 | } 164 | } 165 | 166 | return $this; 167 | } 168 | 169 | /** 170 | * Set table rows. 171 | * 172 | * @param array $rows 173 | * 174 | * @return $this 175 | */ 176 | public function setRows($rows = []) 177 | { 178 | if (!is_array($rows) && !$rows instanceof TableRow) { 179 | throw new \Exception('Rows format error!'); 180 | } 181 | 182 | $rows = $rows instanceof TableRow ? [$rows] : $rows; 183 | 184 | $this->rows = array_merge($this->rows, $rows); 185 | 186 | $formatId = ''; 187 | 188 | foreach ($this->rows as $row) { 189 | 190 | $row->setTable($this->fromTable); 191 | 192 | foreach ($row->geFields() as $field) { 193 | 194 | if ($this->form instanceof WidgetForm) { 195 | 196 | $field->setWidgetForm($this->form); 197 | } else { 198 | 199 | $field->setForm($this->form); 200 | } 201 | 202 | $column = $row->columnStr($field->column()); 203 | 204 | $formatId .= $column; 205 | } 206 | 207 | $row->bindRows(); 208 | } 209 | 210 | $formatId = md5($formatId); 211 | 212 | $this->setErrorKey($formatId); 213 | 214 | $this->id = $formatId; 215 | 216 | return $this; 217 | } 218 | 219 | /** 220 | * Set table style. 221 | * 222 | * @param array $style 223 | * 224 | * @return $this 225 | */ 226 | public function tableStyle($style = []) 227 | { 228 | $this->fromTable->setStyle($style); 229 | 230 | return $this; 231 | } 232 | 233 | /** 234 | * Set table class style. 235 | * 236 | * @param array $style 237 | * 238 | * @return $this 239 | */ 240 | public function tableClass($style = []) 241 | { 242 | $this->fromTable->class($this->defaultClass . implode(' ', $style)); 243 | return $this; 244 | } 245 | 246 | /** 247 | * get inner FromTable 248 | * 249 | * @return FromTable 250 | */ 251 | public function getFromTable() 252 | { 253 | return $this->fromTable; 254 | } 255 | 256 | /** 257 | * Get validator for this field. 258 | * 259 | * @param array $input 260 | * 261 | * @return bool|Validator 262 | */ 263 | public function getValidator(array $input) 264 | { 265 | return $this->validatFields($input); 266 | } 267 | 268 | /** 269 | * Get validator form fields. 270 | * 271 | * @param [type] $input 272 | * @return void 273 | */ 274 | public function validatFields($input) 275 | { 276 | $collectValidator = new CollectValidator; 277 | 278 | foreach ($this->rows as $row) { 279 | 280 | foreach ($row->geFields() as $field) { 281 | 282 | $collectValidator->pushField($field); 283 | } 284 | } 285 | 286 | return $collectValidator->validationMessages($input, $this->getErrorKey()); 287 | } 288 | 289 | /** 290 | * Get fields of this. 291 | * 292 | * @return array 293 | */ 294 | public function getFields() 295 | { 296 | $fields = []; 297 | 298 | foreach ($this->rows as $row) { 299 | 300 | foreach ($row->geFields() as $field) { 301 | $fields[] = $field; 302 | } 303 | } 304 | 305 | return $fields; 306 | } 307 | 308 | /** 309 | * Fill data to the field. 310 | * 311 | * @param array $data 312 | * 313 | * @return void 314 | */ 315 | public function fill($data) 316 | { 317 | $this->fillFields($data); 318 | } 319 | 320 | /** 321 | * Set original value to the field. 322 | * 323 | * @param array $data 324 | * 325 | * @return void 326 | */ 327 | public function setOriginal($data) 328 | { 329 | foreach ($this->rows as $row) { 330 | 331 | foreach ($row->geFields() as $field) { 332 | $field->setOriginal($data); 333 | } 334 | } 335 | } 336 | 337 | /** 338 | * Fill data to the fields. 339 | * 340 | * @param [type] $data 341 | * @return void 342 | */ 343 | public function fillFields($data) 344 | { 345 | foreach ($this->rows as $row) { 346 | 347 | foreach ($row->geFields() as $field) { 348 | $field->fill($data); 349 | } 350 | } 351 | } 352 | 353 | /** 354 | * Build fields 355 | * 356 | * @return void 357 | */ 358 | protected function buildRows() 359 | { 360 | if (!$this->id) { 361 | $this->setRows(); 362 | } 363 | 364 | foreach ($this->rows as $row) { 365 | 366 | foreach ($row->geFields() as $field) { 367 | 368 | if (!$this->fromTable->usingDiv()) { 369 | 370 | if (!$field instanceof Show) { 371 | $field->setLabelClass(['hidden'])->attribute(['title' => $field->label()]); 372 | } 373 | 374 | $field->setWidth(12, 0); 375 | } else { 376 | 377 | $row->autoSpan(); 378 | } 379 | } 380 | } 381 | 382 | $this->fromTable->setRows($this->rows); 383 | } 384 | 385 | /** 386 | * Create a row 387 | * 388 | * @return void 389 | */ 390 | public function row(Closure $callback) 391 | { 392 | $tableRow = new TableRow(); 393 | 394 | call_user_func($callback, $tableRow); 395 | 396 | $this->rows[] = $tableRow; 397 | } 398 | 399 | /** 400 | * Render this filed. 401 | * 402 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 403 | */ 404 | public function render() 405 | { 406 | $this->buildRows(); 407 | 408 | $this->addVariables([ 409 | 'table' => $this->fromTable->render(), 410 | ]); 411 | 412 | return view($this->getView(), $this->variables()); 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/TableExtension.php: -------------------------------------------------------------------------------- 1 | fields; 91 | } 92 | 93 | /** 94 | * @param Field $field 95 | * 96 | * @return $this 97 | */ 98 | public function pushField(Field $field, $colspan = 1) 99 | { 100 | $column = $this->columnStr($field->column()); 101 | 102 | $label = $field->label(); 103 | 104 | if ($this->bind_rows) { 105 | 106 | admin_error('Error', "Don not pushField '{$label}' after \$table->setRows(\$tableRow) was called!"); 107 | 108 | return $this; 109 | } 110 | 111 | $this->fields[] = $field; 112 | 113 | $this->col_spans[$column] = is_numeric($colspan) ? $colspan : 1; 114 | 115 | return $this; 116 | } 117 | 118 | /** 119 | * @return $this 120 | */ 121 | public function bindRows() 122 | { 123 | $this->bind_rows = true; 124 | 125 | return $this; 126 | } 127 | 128 | /** 129 | * Auto set Width 130 | * @return $this 131 | */ 132 | public function autoSpan() 133 | { 134 | $defaults = 0; 135 | 136 | $use = 0; 137 | 138 | foreach ($this->fields as $field) { 139 | 140 | $width = $this->getSpan($field->column()); 141 | 142 | if ($width == 1) { 143 | 144 | $defaults += 1; 145 | } 146 | 147 | $use += $width; 148 | } 149 | 150 | $rows = count($this->fields); 151 | 152 | if ($defaults == $rows) { 153 | 154 | $this->col_spans = []; 155 | 156 | foreach ($this->fields as $field) { 157 | 158 | $column = $this->columnStr($field->column()); 159 | 160 | if ($rows >= 4) { 161 | 162 | $this->col_spans[$column] = 3; 163 | 164 | $field->setWidth(6, 6); 165 | } else if ($rows == 3) { 166 | 167 | $this->col_spans[$column] = 4; 168 | 169 | $field->setWidth(8, 4); 170 | } else if ($rows == 2) { 171 | 172 | $this->col_spans[$column] = 6; 173 | 174 | $field->setWidth(8, 2); 175 | } else { 176 | 177 | $this->col_spans[$column] = 12; 178 | 179 | $field->setWidth(10, 2); 180 | } 181 | } 182 | } 183 | 184 | return $this; 185 | } 186 | 187 | /** 188 | * get rwo_span of column 189 | * 190 | * @return int 191 | */ 192 | public function getSpan($columns) 193 | { 194 | $columns = $this->columnStr($columns); 195 | 196 | if (empty($this->col_spans)) { 197 | return 1; 198 | } 199 | 200 | if (!array_key_exists($columns, $this->col_spans)) { 201 | return 1; 202 | } 203 | 204 | return $this->col_spans[$columns] ?: 1; 205 | } 206 | 207 | /** 208 | * set col_spans 209 | * 210 | * @return $this 211 | */ 212 | public function setcolspans(array $col_spans) 213 | { 214 | $this->col_spans = $col_spans; 215 | return $this; 216 | } 217 | 218 | /** 219 | * set table 220 | * 221 | * @return $this 222 | */ 223 | public function setTable($table) 224 | { 225 | $this->table = $table; 226 | return $this; 227 | } 228 | 229 | /** 230 | * get column as string 231 | * 232 | * @param string|array $columns 233 | * @return string 234 | */ 235 | public function columnStr($columns) 236 | { 237 | $key = $columns; 238 | 239 | if (is_array($columns)) { //Elements has more than 2 arguments : [dateRange / datetimeRange / latlong] , they column is array; 240 | 241 | $key = implode('_', array_values($columns)); 242 | } 243 | 244 | return $key; 245 | } 246 | 247 | /** 248 | * Generate a Field object and add to form builder if Field exists. 249 | * 250 | * @param string $method 251 | * @param array $arguments 252 | * 253 | * @return Field 254 | */ 255 | public function __call($method, $arguments) 256 | { 257 | if ($className = Form::findFieldClass($method)) { 258 | 259 | $column = Arr::get($arguments, 0, ''); 260 | 261 | $arguments = array_slice($arguments, 1); 262 | 263 | $count = count($arguments); 264 | 265 | $colspan = 1; 266 | 267 | if ($count > 0) { 268 | // $form->text($column, $label); Most of the elements has 2 arguments; 269 | // $form->dateRange($startDate, $endDate, $label); //Elements has more than 2 arguments : [dateRange / datetimeRange / latlong]; 270 | 271 | // last of arguments is label 272 | $label = $arguments[$count - 1]; 273 | 274 | if (is_numeric($label)) { // if the last is number 275 | 276 | //Exemple: 277 | // $form->text($column, $label, 2); // 2 is colspan 278 | // $form->dateRange($startDate, $endDate, $label, 2); 279 | 280 | $colspan = intval($label); 281 | } 282 | } 283 | 284 | $element = new $className($column, $arguments); 285 | 286 | if (!$this->bind_rows) { 287 | 288 | $element->setWidth(8, 4); 289 | 290 | $this->pushField($element, $colspan); 291 | 292 | return $element; 293 | } 294 | 295 | $args = $label ? "'{$column}', '$label'" : "$column"; 296 | 297 | admin_error('Error', "Don not call \$tableRow->{$method}('{$args}') after \$table->setRows(\$tableRow) was called!"); 298 | 299 | return new Field\Nullable(); 300 | } 301 | 302 | admin_error('Error', "Field type [$method] does not exist."); 303 | 304 | return new Field\Nullable(); 305 | } 306 | } 307 | --------------------------------------------------------------------------------