├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── roadmap.md └── src ├── Bootstrap4FormsFacade.php ├── Bootstrap4FormsServiceProvider.php ├── FormBuilder.php └── FormService.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | roadmap.md 3 | 4 | /.idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Sean Tymon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap 4 forms for Laravel 5/6/7/8 2 | 3 | [![Latest Version on Packagist][ico-version]][link-packagist] 4 | [![Total Downloads][ico-downloads]][link-downloads] 5 | 6 | This is a package for creating Bootstrap 4 styled form elements in Laravel 5/6. 7 | 8 | ## Features 9 | 10 | - Labels 11 | - Error messages 12 | - Bootstrap 4 markup and classes (including state, colors, and sizes) 13 | - Error validation messages 14 | - Form fill (using Model instance, array or after form submission when a validation error occurs) 15 | - Internationalization 16 | - Add parameters using php chaining approach 17 | - Zero dependences (no Laravel Collective dependency) 18 | 19 | ## Introduction 20 | 21 | ### Before 22 | 23 | ```html 24 |
25 | 26 | 32 | @if($errors->has('username')) 33 |
{{$errors->first('username')}}
34 | @endif 35 |
36 | ``` 37 | 38 | ### After 39 | 40 | ```php 41 | Form::text('username', 'Username') 42 | ``` 43 | 44 | ## Installation 45 | 46 | #### Require the package using Composer. 47 | 48 | ```bash 49 | composer require netojose/laravel-bootstrap-4-forms 50 | ``` 51 | 52 | ### Laravel 5.5 or above 53 | 54 | If you is using Laravel 5.5, the auto discovery feature will make everything for you and your job is done, you can start using now. Else, follow the steps below to install. 55 | 56 | ### Laravel 5.4 57 | 58 | #### Add the service provider to your config/app.php file 59 | 60 | ```php 61 | 'providers' => [ 62 | //... 63 | NetoJose\Bootstrap4Forms\Bootstrap4FormsServiceProvider::class, 64 | ], 65 | ``` 66 | 67 | #### Add the BootForm facade to the aliases array in config/app.php: 68 | 69 | ```php 70 | 'aliases' => [ 71 | //... 72 | 'Form' => NetoJose\Bootstrap4Forms\Bootstrap4FormsFacade::class, 73 | ], 74 | ``` 75 | 76 | ## Usage 77 | 78 | ### Basic form controls 79 | 80 | #### Opening and closing a form 81 | 82 | ```php 83 | // Opening a form using POST method 84 | 85 | {!!Form::open()!!} 86 | // ... Form components here 87 | {!!Form::close()!!} 88 | ``` 89 | 90 | > Opening the form will add \_token field automatically for you 91 | 92 | #### Inline form 93 | 94 | ```php 95 | // Making all inputs inline 96 | {!!Form::open()->formInline()!!} 97 | 98 | // You can use FALSE to turn off disable form inline 99 | {!!Form::open()->formInline(false)!!} 100 | ``` 101 | 102 | #### Fieldset 103 | 104 | | Param | Type | Default | Description | 105 | | -------- | ------ | ------- | --------------- | 106 | | \$legend | string | null | Fieldset Legend | 107 | 108 | ```php 109 | // Example 110 | {!!Form::fieldsetOpen('Legend title')!!} 111 | // ... fieldset content 112 | {!!Form::fieldsetClose()!!} 113 | ``` 114 | 115 | ### Basic inputs 116 | 117 | #### Text inputs 118 | 119 | | Param | Type | Default | Description | 120 | | --------- | ------ | ------- | ------------- | 121 | | \$name | string | null | Input name | 122 | | \$label | string | null | Input label | 123 | | \$default | string | null | Default value | 124 | 125 | ```php 126 | // Example 127 | {!!Form::text('name', 'User name')!!} 128 | ``` 129 | 130 | ##### Textarea 131 | 132 | | Param | Type | Default | Description | 133 | | --------- | ------ | ------- | ------------- | 134 | | \$name | string | null | Input name | 135 | | \$label | string | null | Input label | 136 | | \$default | string | null | Default value | 137 | 138 | ```php 139 | // Example 140 | {!!Form::textarea('description', 'Description')!!} 141 | ``` 142 | 143 | ##### Select 144 | 145 | | Param | Type | Default | Description | 146 | | --------- | ------ | ------- | -------------- | 147 | | \$name | string | null | Input name | 148 | | \$label | string | null | Input label | 149 | | \$options | array | [] | Select options | 150 | | \$default | string | null | Default value | 151 | 152 | ```php 153 | // Example 154 | {!!Form::select('city', 'Choose your city', [1 => 'Gotham City', 2 => 'Springfield'])!!} 155 | ``` 156 | 157 | ##### Options 158 | 159 | | Param | Type | Default | Description | 160 | | ---------- | -------- | ------- | ------------- | 161 | | \$options | iterable | [] | Options list | 162 | | \$valueKey | string | null | key for value | 163 | | \$idKey | string | null | key for id | 164 | 165 | ```php 166 | // Example 167 | 168 | // With array 169 | {!!Form::select('city', 'Choose your city')->options([1 => 'Gotham City', 2 => 'Springfield'])!!} 170 | 171 | // With collection 172 | $cities = collect([1 => 'Gotham City', 2 => 'Springfield']) 173 | {!!Form::select('city', 'Choose your city')->options($cities)!!} 174 | 175 | // With model collection 176 | $cities = \App\City::all(); 177 | {!!Form::select('city', 'Choose your city')->options($cities)!!} 178 | 179 | // Your model should have id and name attributes. If these keys are different, you can pass second and/or third parameters (you can use the second parameter to access some model acessor, also) 180 | $cities = \App\City::all(); 181 | {!!Form::select('city', 'Choose your city')->options($cities, 'city_name', 'id_object_field')!!} 182 | 183 | // When you are using collections, you can use prepend method (https://laravel.com/docs/5.8/collections#method-prepend) to add an first empty value, like "Choose your city" 184 | $cities = \App\City::all(); 185 | {!!Form::select('city', 'Choose your city')->options($cities->prepend('Choose your city', ''))!!} 186 | ``` 187 | 188 | ##### Checkbox 189 | 190 | | Param | Type | Default | Description | 191 | | --------- | ------- | ------- | ------------- | 192 | | \$name | string | null | Input name | 193 | | \$label | string | null | Input label | 194 | | \$value | string | null | Input value | 195 | | \$checked | boolean | null | Default value | 196 | 197 | ```php 198 | // Example 199 | {!!Form::checkbox('orange', 'Orange')!!} 200 | ``` 201 | 202 | ##### Radio 203 | 204 | | Param | Type | Default | Description | 205 | | --------- | ------- | ------- | ------------- | 206 | | \$name | string | null | Input name | 207 | | \$label | string | null | Input label | 208 | | \$value | string | null | Input value | 209 | | \$checked | boolean | null | Default value | 210 | 211 | ```php 212 | // Example 213 | {!!Form::radio('orange', 'Orange')!!} 214 | ``` 215 | 216 | ##### File 217 | 218 | | Param | Type | Default | Description | 219 | | ------- | ------ | ------- | ----------- | 220 | | \$name | string | null | Input name | 221 | | \$label | string | null | Input label | 222 | 223 | ```php 224 | // Example 225 | {!!Form::file('doc', 'Document')!!} 226 | ``` 227 | 228 | #### Date inputs 229 | 230 | | Param | Type | Default | Description | 231 | | --------- | ------ | ------- | ------------- | 232 | | \$name | string | null | Input name | 233 | | \$label | string | null | Input label | 234 | | \$default | string | null | Default value | 235 | 236 | ```php 237 | // Example 238 | {!!Form::date('birthday', 'Birthday')!!} 239 | ``` 240 | 241 | #### Tel inputs 242 | 243 | | Param | Type | Default | Description | 244 | | --------- | ------ | ------- | ------------- | 245 | | \$name | string | null | Input name | 246 | | \$label | string | null | Input label | 247 | | \$default | string | null | Default value | 248 | 249 | ```php 250 | // Example 251 | {!!Form::tel('number', 'Phone number')!!} 252 | ``` 253 | 254 | #### Time inputs 255 | 256 | | Param | Type | Default | Description | 257 | | --------- | ------ | ------- | ------------- | 258 | | \$name | string | null | Input name | 259 | | \$label | string | null | Input label | 260 | | \$default | string | null | Default value | 261 | 262 | ```php 263 | // Example 264 | {!!Form::time('hour', 'Meeting hour')!!} 265 | ``` 266 | 267 | #### URL inputs 268 | 269 | | Param | Type | Default | Description | 270 | | --------- | ------ | ------- | ------------- | 271 | | \$name | string | null | Input name | 272 | | \$label | string | null | Input label | 273 | | \$default | string | null | Default value | 274 | 275 | ```php 276 | // Example 277 | {!!Form::urlInput('website', 'You website')!!} 278 | ``` 279 | 280 | #### Range inputs 281 | 282 | | Param | Type | Default | Description | 283 | | --------- | ------ | ------- | ------------- | 284 | | \$name | string | null | Input name | 285 | | \$label | string | null | Input label | 286 | | \$default | string | null | Default value | 287 | 288 | ```php 289 | // Example 290 | {!!Form::range('name', 'User name')!!} 291 | ``` 292 | 293 | ##### Hidden 294 | 295 | | Param | Type | Default | Description | 296 | | --------- | ------- | ------- | ------------- | 297 | | \$name | string | null | Input name | 298 | | \$default | boolean | null | Default value | 299 | 300 | ```php 301 | // Example 302 | {!!Form::hidden('user_id')!!} 303 | ``` 304 | 305 | ##### Anchor 306 | 307 | | Param | Type | Default | Description | 308 | | ------- | ------ | ------- | ----------- | 309 | | \$value | string | null | Anchor text | 310 | | \$url | string | null | Anchor url | 311 | 312 | ```php 313 | // Example 314 | {!!Form::anchor("Link via parameter", 'foo/bar')!!} 315 | ``` 316 | 317 | ##### Buttons 318 | 319 | | Param | Type | Default | Description | 320 | | ------- | ------ | ------- | ------------ | 321 | | \$value | string | null | Button value | 322 | | \$color | string | null | Button color | 323 | | \$size | string | null | button size | 324 | 325 | ###### Submit 326 | 327 | ```php 328 | // Example 329 | {!!Form::submit("Send form")!!} 330 | ``` 331 | 332 | ###### Button 333 | 334 | ```php 335 | // Example 336 | {!!Form::button("Do something", "warning", "lg")!!} 337 | ``` 338 | 339 | ###### Reset 340 | 341 | ```php 342 | // Example 343 | {!!Form::reset("Clear form")!!} 344 | ``` 345 | 346 | ### Chainable methods 347 | 348 | > This package uses [chaining](https://en.wikipedia.org/wiki/Method_chaining) feature, allowing easly pass more parameters. 349 | 350 | ### Filling a form 351 | 352 | | Param | Type | Default | Description | 353 | | ------ | ------------ | ------- | ------------------------ | 354 | | \$data | object/array | array | Data fo fill form inputs | 355 | 356 | ```php 357 | // Examples 358 | 359 | // With initial data using a Model instance 360 | $user = User::find(1); 361 | {!!Form::open()->fill($user)!!} 362 | 363 | // With initial array data 364 | $user = ['name' => 'Jesus', 'age' => 33]; 365 | {!!Form::open()->fill($user)!!} 366 | ``` 367 | 368 | ### Url 369 | 370 | Use in anchors and forms openings 371 | 372 | | Param | Type | Default | Description | 373 | | ----- | ------ | ------- | ----------- | 374 | | \$url | string | null | Url | 375 | 376 | ```php 377 | // Example 378 | {!!Form::anchor("Link via url")->url('foo/bar')!!} 379 | ``` 380 | 381 | ### Route 382 | 383 | Use in anchors and forms openings 384 | 385 | | Param | Type | Default | Description | 386 | | ------- | ------ | ------- | ----------- | 387 | | \$route | string | null | Route name | 388 | 389 | ```php 390 | // Example 391 | {!!Form::anchor("Link via route")->route('home')!!} 392 | ``` 393 | 394 | ### Error Bag 395 | 396 | Use if you have more then one form per page. You set an identifier for each form, and the errors will be attached for that specific form 397 | 398 | | Param | Type | Default | Description | 399 | | ------- | ------ | ------- | -------------- | 400 | | \$value | string | null | Error bag name | 401 | 402 | ```php 403 | // Example: attach this form to a error bag called "registerErrorBag" 404 | {!!Form::open()->route('register.post')->errorBag("registerErrorBag")!!} 405 | 406 | // ------------------------------------------------------ 407 | 408 | // Now, in your controller (register.post route), you can redirect the user to a form page again, with erros inside a error bag called "registerErrorBag" 409 | public function register(Request $request) 410 | { 411 | $validator = Validator::make($request->all(), [ 412 | // ... rules here 413 | ]); 414 | 415 | if ($validator->fails()) { 416 | return redirect() 417 | ->route('register.form') 418 | ->withInput() 419 | ->withErrors($validator, 'registerErrorBag'); 420 | } 421 | 422 | // Proced to register here 423 | } 424 | 425 | // ------------------------------------------------------ 426 | 427 | // If your validation is on a Form Request, you can add a protected method "$errorBag" to set a ErrorBag name 428 | 429 | class RegisterRequest extends FormRequest 430 | { 431 | 432 | protected $errorBag = 'registerErrorBag'; 433 | 434 | public function authorize() 435 | { 436 | return true; 437 | } 438 | 439 | public function rules() 440 | { 441 | return [ 442 | // ... rules here 443 | ]; 444 | } 445 | } 446 | ``` 447 | 448 | ### Errors 449 | 450 | Show all errors inside a panel 451 | 452 | | Param | Type | Default | Description | 453 | | ------- | ------ | ------- | ----------- | 454 | | \$title | string | null | Panel title | 455 | 456 | ```php 457 | // Example 458 | {!!Form::errors("The form has errors")!!} 459 | ``` 460 | 461 | ### Disable validation messages 462 | 463 | Disable success/error status and validation error message 464 | 465 | | Param | Type | Default | Description | 466 | | ---------- | ------- | ------- | --------------- | 467 | | \$disabled | boolean | false | Disabled status | 468 | 469 | ```php 470 | // Example 471 | {!!Form::text('username', 'User name')->disableValidation()!!} 472 | 473 | // You can use FALSE to turn off disable validation (to enable it) 474 | {!!Form::text('username', 'User name')->disableValidation(false)!!} 475 | ``` 476 | 477 | ### Checked 478 | 479 | Set the checkbox/radio checked status 480 | 481 | | Param | Type | Default | Description | 482 | | --------- | ------- | ------- | -------------- | 483 | | \$checked | boolean | true | Checked status | 484 | 485 | ```php 486 | // Examples 487 | 488 | // Using readonly field 489 | {!!Form::checkbox('agree', 'I agree')->checked()!!} 490 | 491 | // You can use FALSE to turn off checked status 492 | {!!Form::checkbox('agree', 'I agree')->checked(false)!!} 493 | ``` 494 | 495 | ### Inline 496 | 497 | Set the checkbox/radio checked status 498 | 499 | ```php 500 | // Examples 501 | {!!Form::radio('orange', 'Orange')->inline()!!} 502 | 503 | {!!Form::checkbox('orange', 'Orange')->inline()!!} 504 | 505 | // You can use FALSE to turn off inline status 506 | {!!Form::checkbox('orange', 'Orange')->inline(false)!!} 507 | ``` 508 | 509 | ### Placeholder 510 | 511 | | Param | Type | Default | Description | 512 | | ------------- | ------ | ------- | ---------------- | 513 | | \$placeholder | string | null | Placeholder text | 514 | 515 | ```php 516 | // Example 517 | {!!Form::text('name', 'Name')->placeholder('Input placeholder')!!} 518 | ``` 519 | 520 | ### Select Multiple 521 | 522 | ```php 523 | // Example 524 | {!!Form::select('city', 'Choose your city', [1 => 'Gotham City', 2 => 'Springfield'])->multiple()!!} 525 | ``` 526 | 527 | ### Locale 528 | 529 | Using locale, the package will look for a resources/lang/{CURRENT_LANG}/forms/user.php language file and uses labels and help texts as keys for replace texts 530 | 531 | ```php 532 | // Example 533 | {!!Form::open()->locale('forms.user')!!} 534 | ``` 535 | 536 | ### Help Text 537 | 538 | | Param | Type | Default | Description | 539 | | ------ | ------ | ------- | ----------- | 540 | | \$text | string | null | Help text | 541 | 542 | ```php 543 | // Example 544 | {!!Form::text('name', 'Name')->help('Help text here')!!} 545 | ``` 546 | 547 | ### Custom attributes 548 | 549 | | Param | Type | Default | Description | 550 | | ------- | ----- | ------- | ----------------------- | 551 | | \$attrs | array | [] | Custom input attributes | 552 | 553 | ```php 554 | // Example 555 | {!!Form::text('name', 'Name')->attrs(['data-foo' => 'bar', 'rel'=> 'baz'])!!} 556 | ``` 557 | 558 | ### Custom attributes in wrapper div (\
...\
) 559 | 560 | | Param | Type | Default | Description | 561 | | ------- | ----- | ------- | ----------------------- | 562 | | \$attrs | array | [] | Custom input attributes | 563 | 564 | ```php 565 | // Example 566 | {!!Form::text('name', 'Name')->wrapperAttrs(['data-foo' => 'bar', 'id'=> 'name-wrapper'])!!} 567 | ``` 568 | 569 | ### Readonly 570 | 571 | | Param | Type | Default | Description | 572 | | -------- | ------- | ------- | ---------------- | 573 | | \$status | boolean | true | Read only status | 574 | 575 | ```php 576 | // Examples 577 | 578 | // Using readonly field 579 | {!!Form::text('name', 'Name')->readonly()!!} 580 | 581 | // You can use FALSE to turn off readonly status 582 | {!!Form::text('name', 'Name')->readonly(false)!!} 583 | ``` 584 | 585 | ### Disabled 586 | 587 | | Param | Type | Default | Description | 588 | | -------- | ------- | ------- | --------------- | 589 | | \$status | boolean | true | Disabled status | 590 | 591 | ```php 592 | // Examples 593 | 594 | // Disabling a field 595 | {!!Form::text('name', 'Name')->disabled()!!} 596 | 597 | // Disabling a fieldset 598 | {!!Form::fieldsetOpen('User data')->disabled()!!} 599 | 600 | // You can use FALSE to turn off disabled status 601 | {!!Form::text('name', 'Name')->disabled(false)!!} 602 | ``` 603 | 604 | ### Block 605 | 606 | | Param | Type | Default | Description | 607 | | -------- | ------- | ------- | --------------- | 608 | | \$status | boolean | true | Disabled status | 609 | 610 | ```php 611 | // Examples 612 | 613 | // Disabling a field 614 | {!!Form::text('name', 'Name')->block()!!} 615 | 616 | // You can use FALSE to turn off block status 617 | {!!Form::text('name', 'Name')->block(false)!!} 618 | ``` 619 | 620 | ### Required 621 | 622 | | Param | Type | Default | Description | 623 | | -------- | ------- | ------- | --------------- | 624 | | \$status | boolean | true | Required status | 625 | 626 | ```php 627 | // Examples 628 | 629 | // Disabling a field 630 | {!!Form::text('name', 'Name')->required()!!} 631 | 632 | // Disabling a fieldset 633 | {!!Form::fieldsetOpen('User data')->required()!!} 634 | 635 | // You can use FALSE to turn off required status 636 | {!!Form::text('name', 'Name')->required(false)!!} 637 | ``` 638 | 639 | ### AutoFill 640 | 641 | | Param | Type | Default | Description | 642 | | ------- | ------ | ------- | ----------------- | 643 | | \$value | string | 'on' | autocomplte value | 644 | 645 | see: https://html.spec.whatwg.org/multipage/forms.html#autofill 646 | 647 | If no autocomplete value is specified on the form, html spec requires 648 | a default value of 'on'. So, you must explicitly turn it off. 649 | 650 | Autocomplete values will be automatically generated for fields with 651 | single word names matching valid values (e.g. name, email, tel, organization). The 652 | complete list is in the spec mentioned above. 653 | 654 | ```php 655 | // Examples 656 | 657 | // Switch off autocomplete for the form 658 | {!!Form::open()->autocomplete('off')!!} 659 | 660 | // Explicitly set a autocomplete value 661 | {!!Form::text('mobile', 'Mobile Number')->autocomplete('tel')!!} 662 | 663 | // Disable autocomplete for fields with valid names 664 | {!!Form::text('name', 'Name')->autocomplete('off')!!} 665 | ``` 666 | 667 | ### Id 668 | 669 | | Param | Type | Default | Description | 670 | | ----- | ------ | ------- | ----------- | 671 | | \$id | string | null | Id field | 672 | 673 | ```php 674 | // Example 675 | {!!Form::text('name', 'Name')->id('user-name')!!} 676 | ``` 677 | 678 | ### Id prefix 679 | 680 | | Param | Type | Default | Description | 681 | | -------- | ------ | ------- | ----------- | 682 | | \$prefix | string | null | Id prefix | 683 | 684 | ```php 685 | // Example 686 | {!!Form::open()->idPrefix('register')!!} 687 | ``` 688 | 689 | ### Multipart 690 | 691 | | Param | Type | Default | Description | 692 | | ----------- | ------- | ------- | -------------- | 693 | | \$multipart | boolean | true | Multipart flag | 694 | 695 | ```php 696 | // Examples 697 | {!!Form::open()->multipart()!!} 698 | 699 | // You can use FALSE to turn off multipart 700 | {!!Form::open()->multipart(false)!!} 701 | ``` 702 | 703 | ### Method 704 | 705 | | Param | Type | Default | Description | 706 | | -------- | ------ | ------- | ----------- | 707 | | \$method | string | null | HTTP method | 708 | 709 | ```php 710 | // Examples 711 | {!!Form::open()->method('get')!!} 712 | {!!Form::open()->method('post')!!} 713 | {!!Form::open()->method('put')!!} 714 | {!!Form::open()->method('patch')!!} 715 | {!!Form::open()->method('delete')!!} 716 | ``` 717 | 718 | ### explicit HTTP verbs 719 | 720 | ```php 721 | // Examples 722 | {!!Form::open()->get()!!} 723 | {!!Form::open()->post()!!} 724 | {!!Form::open()->put()!!} 725 | {!!Form::open()->patch()!!} 726 | {!!Form::open()->delete()!!} 727 | ``` 728 | 729 | ### Color 730 | 731 | | Param | Type | Default | Description | 732 | | ------- | ------ | ------- | ----------- | 733 | | \$color | string | null | Color name | 734 | 735 | ```php 736 | // Examples 737 | {!!Form::button("Do something")->color("warning")!!} 738 | 739 | {!!Form::button("Do something")->color("primary")!!} 740 | ``` 741 | 742 | ### explicit color 743 | 744 | ```php 745 | // Examples 746 | {!!Form::button("Button label")->warning()!!} 747 | {!!Form::button("Button label")->outline()!!} 748 | {!!Form::button("Button label")->success()!! 749 | {!!Form::button("Button label")->danger()!!} 750 | {!!Form::button("Button label")->secondary()!!} 751 | {!!Form::button("Button label")->info()!!} 752 | {!!Form::button("Button label")->light()!!} 753 | {!!Form::button("Button label")->dark()!!} 754 | {!!Form::button("Button label")->link()!!} 755 | ``` 756 | 757 | ### Size 758 | 759 | | Param | Type | Default | Description | 760 | | ------ | ------ | ------- | ----------- | 761 | | \$size | string | null | Size name | 762 | 763 | ```php 764 | // Examples 765 | {!!Form::button("Do something")->size("sm")!!} 766 | 767 | {!!Form::button("Do something")->size("lg")!!} 768 | ``` 769 | 770 | ### Explicit size 771 | 772 | ```php 773 | // Examples 774 | {!!Form::button("Button label")->sm()!!} 775 | {!!Form::button("Button label")->lg()!!} 776 | ``` 777 | 778 | ### Type 779 | 780 | | Param | Type | Default | Description | 781 | | ------ | ------ | ------- | ----------- | 782 | | \$type | string | null | Type field | 783 | 784 | ```php 785 | // Examples 786 | 787 | // Password field 788 | {!!Form::text('password', 'Your password')->type('password')!!} 789 | 790 | // Number field 791 | {!!Form::text('age', 'Your age')->type('number')!!} 792 | 793 | // Email field 794 | {!!Form::text('email', 'Your email')->type('email')!!} 795 | ``` 796 | 797 | ### Min 798 | 799 | | Param | Type | Default | Description | 800 | | ------- | ------ | ------- | ------------- | 801 | | \$value | number | null | Minimum value | 802 | 803 | Set min attribute for input 804 | 805 | ```php 806 | // Example 807 | {!!Form::text('age', 'Your age')->type('number')->min(18)!!} 808 | ``` 809 | 810 | ### Max 811 | 812 | | Param | Type | Default | Description | 813 | | ------- | ------ | ------- | ------------- | 814 | | \$value | number | null | Minimum value | 815 | 816 | Set max attribute for input 817 | 818 | ```php 819 | // Example 820 | {!!Form::text('age', 'Your age')->type('number')->max(18)!!} 821 | ``` 822 | 823 | ### Name 824 | 825 | | Param | Type | Default | Description | 826 | | ------ | ------ | ------- | ----------- | 827 | | \$name | string | null | Input name | 828 | 829 | ```php 830 | // Examples 831 | {!!Form::text('text')->name('name')!!} 832 | ``` 833 | 834 | ### Label 835 | 836 | | Param | Type | Default | Description | 837 | | ------- | ------ | ------- | ----------- | 838 | | \$label | string | null | Input label | 839 | 840 | ```php 841 | // Examples 842 | {!!Form::text('age')->label('Your age')!!} 843 | ``` 844 | 845 | ### Default Value 846 | 847 | | Param | Type | Default | Description | 848 | | ------- | ----- | ------- | ----------- | 849 | | \$value | mixed | null | Input value | 850 | 851 | ```php 852 | // Example 853 | {!!Form::text('name', 'Your name')->value('Maria')!!} 854 | ``` 855 | 856 | ### Render 857 | 858 | | Param | Type | Default | Description | 859 | | -------- | ------ | ------- | ----------- | 860 | | \$render | string | null | Render name | 861 | 862 | ```php 863 | // Examples 864 | 865 | // Number field 866 | {!!Form::render('text')->name('age')->label('Your age')!!} 867 | ``` 868 | 869 | ### Disable is-valid CSS Class 870 | 871 | | Param | Type | Default | Description | 872 | | ---------------- | ------- | ------- | -------------------------- | 873 | | \$disableIsValid | boolean | true | Disable is-valid CSS class | 874 | 875 | ```php 876 | // Examples 877 | 878 | // Disable Bootstrap's is-valid CSS class 879 | {!!Form::text('name', 'Name')->disableIsValid()!!} 880 | ``` 881 | 882 | ### Chaining properties 883 | 884 | You can use chaining feature to use a lot of settings for each component 885 | 886 | ```php 887 | // Examples 888 | 889 | {!!Form::open()->locale('forms.user')->put()->multipart()->route('user.add')->data($user)!!} 890 | 891 | {!!Form::text('name', 'Name')->placeholder('Type your name')->lg()!!} 892 | 893 | {!!Form::anchor("Link as a button")->sm()->info()->outline()!!} 894 | 895 | {!!Form::submit('Awesome button')->id('my-btn')->disabled()->danger()->lg()!!} 896 | 897 | {!!Form::close()!!} 898 | ``` 899 | 900 | [ico-version]: https://img.shields.io/packagist/v/netojose/laravel-bootstrap-4-forms.svg?style=flat-square 901 | [ico-downloads]: https://img.shields.io/packagist/dt/netojose/laravel-bootstrap-4-forms.svg?style=flat-square 902 | [link-packagist]: https://packagist.org/packages/netojose/laravel-bootstrap-4-forms 903 | [link-downloads]: https://packagist.org/packages/netojose/laravel-bootstrap-4-forms 904 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "netojose/laravel-bootstrap-4-forms", 3 | "type": "package", 4 | "description": "Bootstrap 4 form builder for Laravel 5", 5 | "keywords": [ 6 | "laravel", 7 | "bootstrap", 8 | "forms", 9 | "php", 10 | "form-builder", 11 | "composer", 12 | "package" 13 | ], 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "José Sousa", 18 | "email": "sputinykster@gmail.com" 19 | } 20 | ], 21 | "version": "3.0.5", 22 | "minimum-stability": "dev", 23 | "require": {}, 24 | "autoload": { 25 | "psr-4": { 26 | "NetoJose\\Bootstrap4Forms\\": "src/" 27 | } 28 | }, 29 | "extra": { 30 | "laravel": { 31 | "providers": [ 32 | "NetoJose\\Bootstrap4Forms\\Bootstrap4FormsServiceProvider" 33 | ], 34 | "aliases": { 35 | "Form": "NetoJose\\Bootstrap4Forms\\Bootstrap4FormsFacade" 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /roadmap.md: -------------------------------------------------------------------------------- 1 | # Future changes 2 | 3 | * add addon for inputs 4 | * add buttons group 5 | -------------------------------------------------------------------------------- /src/Bootstrap4FormsFacade.php: -------------------------------------------------------------------------------- 1 | app->singleton('bootstrap4-form', function() { 14 | return new FormService(); 15 | }); 16 | } 17 | 18 | public function provides() 19 | { 20 | return ['bootstrap4-form']; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/FormBuilder.php: -------------------------------------------------------------------------------- 1 | $formatter($value); 17 | } 18 | $this->attrs[$key] = $value; 19 | } 20 | 21 | private function formatMethod($value) 22 | { 23 | return strtolower($value); 24 | } 25 | 26 | private function formatFormData($value) 27 | { 28 | if (is_object($value) && method_exists($value, 'toArray')) { 29 | return $value->toArray(); 30 | } 31 | return $value; 32 | } 33 | 34 | private function formatOptions($value) 35 | { 36 | extract($this->get('optionIdKey', 'optionValueKey')); 37 | 38 | $idKey = $optionIdKey ?? 'id'; 39 | $valueKey = $optionValueKey ?? 'name'; 40 | 41 | $options = []; 42 | foreach ($value as $key => $item) { 43 | if (is_object($item)) { 44 | $options[$item->{$idKey}] = $item->{$valueKey}; 45 | continue; 46 | } 47 | $options[$key] = $item; 48 | } 49 | return $options; 50 | } 51 | 52 | public function render(): string 53 | { 54 | $render = $this->attrs['render']; 55 | $methodName = 'render' . ucfirst($render); 56 | $output = $this->$methodName(); 57 | $this->resetAttributes(); 58 | return $output; 59 | } 60 | 61 | private function renderFormOpen(): string 62 | { 63 | extract($this->get('id', 'method', 'url', 'formMultipart', 'formInline', 'autocomplete')); 64 | 65 | if (!$method) { 66 | $method = 'post'; 67 | } 68 | 69 | $enctype = $formMultipart ? 'multipart/form-data' : null; 70 | 71 | $attrs = $this->buildHtmlAttrs([ 72 | 'method' => in_array($method, ['get', 'post']) ? $method : 'post', 73 | 'action' => $url, 74 | 'enctype' => $enctype, 75 | 'autocomplete' => $autocomplete, 76 | 'class' => $formInline ? 'form-inline' : null, 77 | 'id' => $id 78 | ]); 79 | 80 | $output = '
'; 81 | 82 | if ($method !== 'get') { 83 | $output .= csrf_field(); 84 | if ($method !== 'post') { 85 | $output .= method_field($method); 86 | } 87 | } 88 | 89 | return $output; 90 | } 91 | 92 | private function renderFormClose(): string 93 | { 94 | $this->resetAttributes(true); 95 | return '
'; 96 | } 97 | 98 | private function renderFieldsetOpen(): string 99 | { 100 | $output = '
'; 101 | extract($this->get('legend')); 102 | 103 | if ($legend) { 104 | $output .= '' . $this->getText($legend) . ''; 105 | } 106 | 107 | return $output; 108 | } 109 | 110 | private function renderFieldsetClose(): string 111 | { 112 | return '
'; 113 | } 114 | 115 | private function renderErrors(): string 116 | { 117 | $errors = $this->errors()->all(); 118 | if (count($errors) < 1) { 119 | return ''; 120 | } 121 | 122 | extract($this->get('errorsHeader', 'id')); 123 | $attrs = $this->buildHtmlAttrs(['class' => 'alert alert-danger', 'role' => 'alert', 'id' => $id]); 124 | $output = '
'; 132 | } 133 | 134 | private function renderInput(): string 135 | { 136 | $attributes = $this->getInputAttributes(); 137 | $attrs = $this->buildHtmlAttrs($attributes); 138 | return $this->wrapperInput(''); 139 | } 140 | 141 | private function renderSelect(): string 142 | { 143 | extract($this->get('options')); 144 | 145 | $fieldValue = $this->getValue(); 146 | $arrValues = is_array($fieldValue) ? $fieldValue : [$fieldValue]; 147 | $optionsList = ''; 148 | foreach ($options as $value => $label) { 149 | $config = []; 150 | if (is_array($label)) { 151 | $config = explode(' ', $label['config']); 152 | $label = $label['label']; 153 | } 154 | $attrs = $this->buildHtmlAttrs([ 155 | 'value' => $value, 156 | 'hidden' => in_array('hidden', $config), 157 | 'disabled' => in_array('disabled', $config), 158 | 'selected' => in_array(strval($value), $arrValues), 159 | ], false); 160 | $optionsList .= ''; 161 | } 162 | 163 | $attributes = $this->getInputAttributes(); 164 | $attrs = $this->buildHtmlAttrs($attributes); 165 | return $this->wrapperInput(''); 166 | } 167 | 168 | private function renderTextarea(): string 169 | { 170 | $attributes = $this->getInputAttributes(); 171 | $value = $attributes['value']; 172 | unset($attributes['value']); 173 | $attrs = $this->buildHtmlAttrs($attributes); 174 | return $this->wrapperInput(''); 175 | } 176 | 177 | private function renderCheckbox(): string 178 | { 179 | $attributes = $this->getInputAttributes(); 180 | $attrs = $this->buildHtmlAttrs($attributes); 181 | return $this->wrapperRadioCheckbox(''); 182 | } 183 | 184 | private function renderRadio(): string 185 | { 186 | $attributes = $this->getInputAttributes(); 187 | $attrs = $this->buildHtmlAttrs($attributes); 188 | return $this->wrapperRadioCheckbox(''); 189 | } 190 | 191 | private function renderAnchor(): string 192 | { 193 | extract($this->get('url', 'value')); 194 | $class = $this->getBtnAnchorClasses(); 195 | $attrs = $this->buildHtmlAttrs(['href' => $url, 'class' => $class]); 196 | return '' . $value . ''; 197 | } 198 | 199 | private function renderButton(): string 200 | { 201 | extract($this->get('type', 'value', 'disabled')); 202 | $class = $this->getBtnAnchorClasses(); 203 | $attrs = $this->buildHtmlAttrs(['type' => $type, 'class' => $class, 'disabled' => $disabled]); 204 | return ''; 205 | } 206 | 207 | private function getBtnAnchorClasses() 208 | { 209 | extract($this->get('size', 'color', 'outline', 'block', 'type', 'value', 'formInline')); 210 | return $this->createAttrsList( 211 | 'btn', 212 | [$size, 'btn-' . $size], 213 | [$color, 'btn-' . ($outline ? 'outline-' : '') . $color], 214 | [$block, 'btn-block'], 215 | [$formInline, 'mx-sm-2'] 216 | ); 217 | } 218 | 219 | private function isRadioOrCheckbox(): bool 220 | { 221 | extract($this->get('render')); 222 | return in_array($render, ['checkbox', 'radio']); 223 | } 224 | 225 | private function getInputAttributes(): array 226 | { 227 | extract($this->get('render', 'type', 'multiple', 'name', 'size', 'placeholder', 'help', 'disabled', 'readonly', 'required', 'autocomplete', 'min', 'max', 'value', 'checked', 'formData', 'disableValidation', 'custom')); 228 | 229 | $isRadioOrCheckbox = $this->isRadioOrCheckbox(); 230 | $type = $isRadioOrCheckbox ? $render : $type; 231 | 232 | $class = 'form-check-input'; 233 | if($custom){ 234 | $class = $this->customClass('input'); 235 | }elseif (!$isRadioOrCheckbox) { 236 | $class = 'form-control'; 237 | switch ($type) { 238 | case 'file': 239 | $class .= '-file'; 240 | break; 241 | case 'range': 242 | $class .= '-range'; 243 | break; 244 | } 245 | 246 | if ($size) { 247 | $class .= ' form-control-' . $size; 248 | } 249 | } 250 | 251 | $id = $this->getId(); 252 | 253 | if (!$disableValidation && $this->errors()->count() > 0) { 254 | $class .= $this->errors()->has($name) ? ' is-invalid' : ' is-valid'; 255 | } 256 | 257 | $attributes = [ 258 | 'type' => $type, 259 | 'name' => $name, 260 | 'id' => $id 261 | ]; 262 | 263 | if ($render !== 'select') { 264 | $attributes['value'] = $this->getValue(); 265 | } else { 266 | $attributes['multiple'] = $multiple; 267 | } 268 | 269 | // If the field is a hidden field, we don't need add more attributes 270 | if ($type === 'hidden') { 271 | return $attributes; 272 | } 273 | 274 | if ($this->isRadioOrCheckbox()) { 275 | if ($this->hasOldInput()) { 276 | $isChecked = old($name) === $value; 277 | } else { 278 | $isChecked = isset($formData[$name]) ? $formData[$name] === $value : $checked; 279 | } 280 | $attributes['checked'] = $isChecked; 281 | } 282 | 283 | return array_merge($attributes, [ 284 | 'class' => $class, 285 | 'min' => $min, 286 | 'max' => $max, 287 | 'autocomplete' => $autocomplete, 288 | 'placeholder' => $this->getText($placeholder), 289 | 'aria-describedby' => $help ? 'help-' . $id : null, 290 | 'disabled' => $disabled, 291 | 'readonly' => $readonly, 292 | 'required' => $required 293 | ]); 294 | } 295 | 296 | private function renderLabel(): string 297 | { 298 | extract($this->get('label', 'formInline', 'render', 'custom')); 299 | 300 | $class = ''; 301 | if($custom){ 302 | $class = $this->customClass('label'); 303 | } elseif (in_array($render, ['checkbox', 'radio'])){ 304 | $class = 'form-check-label'; 305 | } 306 | 307 | if ($formInline) { 308 | $class = join(' ', [$class, 'mx-sm-2']); 309 | } 310 | 311 | $id = $this->getId(); 312 | $attrs = $this->buildHtmlAttrs([ 313 | 'for' => $id, 314 | 'class' => $class 315 | ], false); 316 | return ''; 317 | } 318 | 319 | private function getText($key) 320 | { 321 | extract($this->get('formLocale')); 322 | if ($formLocale) { 323 | return __($formLocale . '.' . $key); 324 | } 325 | return $key; 326 | } 327 | 328 | private function resetAttributes($resetAll = false) 329 | { 330 | // Remove all attributes 331 | if ($resetAll) { 332 | $this->attrs = []; 333 | return; 334 | } 335 | 336 | // Keep attributes which key starting with 'form' 337 | $this->attrs = array_filter($this->attrs, function ($key) { 338 | return substr($key, 0, 4) === 'form'; 339 | }, ARRAY_FILTER_USE_KEY); 340 | } 341 | 342 | private function wrapperInput(string $input): string 343 | { 344 | extract($this->get('type', 'help', 'wrapperAttrs', 'formInline', 'name', 'custom')); 345 | 346 | if ($type === 'hidden') { 347 | return $input; 348 | } 349 | 350 | $id = $this->getId(); 351 | $label = $this->renderLabel(); 352 | $helpText = $help ? '' . $this->getText($help) . '' : ''; 353 | $error = $this->getInputErrorMarkup($name); 354 | $attrs = $wrapperAttrs ?? []; 355 | $attrs['class'] = $this->createAttrsList( 356 | $custom ? $this->customClass('wrapper') : '', 357 | $attrs['class'] ?? null, 358 | $formInline ? 'input-group' : 'form-group' 359 | ); 360 | $attributes = $this->buildHtmlAttrs($attrs, false); 361 | 362 | if($custom && $type === 'file'){ 363 | $placeholder = $label; 364 | $this->set('custom', false); 365 | $label = $this->renderLabel(); 366 | $this->set('custom', true); 367 | return '
' . $label . '
' . $placeholder . $input . $helpText . $error . '
'; 368 | }else{ 369 | return '
' . $label . $input . $helpText . $error . '
'; 370 | } 371 | } 372 | 373 | private function wrapperRadioCheckbox(string $input): string 374 | { 375 | extract($this->get('inline', 'name', 'wrapperAttrs', 'custom')); 376 | 377 | $attrs = $wrapperAttrs ?? []; 378 | $attrs['class'] = $this->createAttrsList( 379 | $custom ? $this->customClass('wrapper') : 'form-check', 380 | [$inline, ($custom ? 'form-check-inline' : 'custom-control-inline')], 381 | $attrs['class'] ?? null 382 | ); 383 | $attributes = $this->buildHtmlAttrs($attrs, false); 384 | $label = $this->renderLabel(); 385 | $error = $this->getInputErrorMarkup($name); 386 | return '
' . $input . $label . $error . '
'; 387 | } 388 | 389 | private function getInputErrorMarkup(string $name): string 390 | { 391 | extract($this->get('disableValidation')); 392 | 393 | if ($disableValidation) { 394 | return ''; 395 | } 396 | 397 | $error = $this->errors()->first($name); 398 | if (!$error) { 399 | return ''; 400 | } 401 | return '
' . $this->errors()->first($name) . '
'; 402 | } 403 | 404 | private function getId() 405 | { 406 | extract($this->get('id', 'name', 'formIdPrefix', 'render', 'value')); 407 | 408 | if ($id) { 409 | return $id; 410 | } 411 | 412 | return ($formIdPrefix ?? 'inp-') . $name . ($render === 'radio' ? '-' . $value : ''); 413 | } 414 | 415 | private function hasOldInput() 416 | { 417 | return count((array) old()) != 0; 418 | } 419 | 420 | private function getValue() 421 | { 422 | extract($this->get('name', 'value', 'formData')); 423 | if ($this->isRadioOrCheckbox()) { 424 | return $value; 425 | } 426 | 427 | if ($this->hasOldInput()) { 428 | if (isset(old()[$name])) { 429 | return old($name, $value); 430 | } 431 | } 432 | 433 | $fromFill = $formData[$name] ?? null; 434 | 435 | return $value ?? $fromFill; 436 | } 437 | 438 | private function buildHtmlAttrs(array $attributes, $appendAttrs = true): string 439 | { 440 | 441 | if ($appendAttrs) { 442 | extract($this->get('attrs')); 443 | $fieldAttrs = $attrs ?? []; 444 | $class = $this->createAttrsList($attributes['class'] ?? null, $fieldAttrs['class'] ?? null); 445 | if ($class) { 446 | $attributes['class'] = $class; 447 | } 448 | $attributes = array_merge($fieldAttrs, $attributes); 449 | } 450 | 451 | return join(' ', array_filter( 452 | array_map(function ($key) use ($attributes) { 453 | $value = $attributes[$key]; 454 | if (is_bool($value)) { 455 | return $value ? $key : ''; 456 | } elseif ($value !== null) { 457 | return $key . '="' . htmlspecialchars($value) . '"'; 458 | } 459 | return ''; 460 | }, array_keys($attributes)) 461 | )); 462 | } 463 | 464 | private function customClass(string $element = 'input') 465 | { 466 | extract($this->get('type', 'size', 'inline', 'render')); 467 | 468 | $type = $type ?? $render; 469 | $input = $element === 'input'; 470 | $wrapper = $element === 'wrapper'; 471 | $label = $element === 'label'; 472 | 473 | if($input){ 474 | $class = 'custom-control-input'; 475 | } elseif($wrapper){ 476 | $class = 'custom-control' . (isset($inline) && $inline ? ' custom-control-inline' : ''); 477 | } else { 478 | $class = 'custom-control-label'; 479 | } 480 | 481 | switch($type){ 482 | case 'checkbox': 483 | if($wrapper){ 484 | $class .= ' custom-checkbox'; 485 | } 486 | break; 487 | case 'radio': 488 | if($wrapper){ 489 | $class .= ' custom-radio'; 490 | } 491 | break; 492 | case 'switch': 493 | if($wrapper){ 494 | $class .= ' custom-switch'; 495 | } 496 | break; 497 | case 'select': 498 | if($input){ 499 | $class = 'custom-select'; 500 | $class = $size ? $class . '-' . $size : $class; 501 | } elseif($label || $wrapper){ 502 | $class = ''; 503 | } 504 | break; 505 | case 'range': 506 | $class = $input ? 'custom-range' : ''; 507 | break; 508 | case 'file': 509 | if($wrapper) { 510 | $class = 'custom-file'; 511 | } elseif($input) { 512 | $class = 'custom-file-input'; 513 | } else{ 514 | $class = 'custom-file-label'; 515 | } 516 | break; 517 | default: 518 | // do nothing 519 | } 520 | return $class; 521 | } 522 | 523 | private function createAttrsList(...$items) 524 | { 525 | $attrs = []; 526 | foreach ($items as $item) { 527 | if (is_array($item)) { 528 | $item = $item[0] ? $item[1] : null; 529 | } 530 | $attrs[] = $item; 531 | } 532 | return join(' ', array_filter($attrs)); 533 | } 534 | 535 | private function errors() 536 | { 537 | $errors = session('errors', app(ViewErrorBag::class)); 538 | extract($this->get('formErrorBag')); 539 | if ($formErrorBag) { 540 | $errors = $errors->{$formErrorBag}; 541 | } 542 | return $errors; 543 | } 544 | 545 | private function get(...$keys): array 546 | { 547 | $return = []; 548 | foreach ($keys as $key) { 549 | $return[$key] = $this->attrs[$key] ?? null; 550 | } 551 | return $return; 552 | } 553 | } 554 | -------------------------------------------------------------------------------- /src/FormService.php: -------------------------------------------------------------------------------- 1 | _builder = new FormBuilder; 19 | } 20 | 21 | /** 22 | * Magic method to return a class string version 23 | * 24 | * @return string 25 | */ 26 | public function __toString() 27 | { 28 | return $this->_builder->render(); 29 | } 30 | 31 | /** 32 | * Set error bag name 33 | * 34 | * @param string $value 35 | * @return FormService 36 | */ 37 | public function errorBag(string $value = null): FormService 38 | { 39 | return $this->_set('formErrorBag', $value); 40 | } 41 | 42 | /** 43 | * Open the form 44 | * 45 | * @return FormService 46 | */ 47 | public function open(): FormService 48 | { 49 | return $this->_set('render', 'formOpen'); 50 | } 51 | 52 | /** 53 | * Close the form 54 | * 55 | * @return FormService 56 | */ 57 | public function close(): FormService 58 | { 59 | return $this->_set('render', 'formClose'); 60 | } 61 | 62 | /** 63 | * Show all validation errors 64 | * 65 | * @param string $title 66 | * @return FormService 67 | */ 68 | public function errors(string $title = null): FormService 69 | { 70 | return $this->_set('render', 'errors')->_set('errorsHeader', $title); 71 | } 72 | 73 | /** 74 | * Set a prefix id for all inputs 75 | * 76 | * @param string $prefix 77 | * @return FormService 78 | */ 79 | public function idPrefix(string $prefix = ''): FormService 80 | { 81 | return $this->_set('formIdPrefix', $prefix); 82 | } 83 | 84 | /** 85 | * Set multipart attribute for a form 86 | * 87 | * @param bool $multipart 88 | * @return FormService 89 | */ 90 | public function multipart(bool $multipart = true): FormService 91 | { 92 | return $this->_set('formMultipart', $multipart); 93 | } 94 | 95 | /** 96 | * Set a method attribute for the form 97 | * 98 | * @param string $method 99 | * @return FormService 100 | */ 101 | public function method(string $method): FormService 102 | { 103 | return $this->_set('method', $method); 104 | } 105 | 106 | /** 107 | * Set get method for the form attribute 108 | * 109 | * @return FormService 110 | */ 111 | public function get(): FormService 112 | { 113 | return $this->method('get'); 114 | } 115 | 116 | /** 117 | * Set post method for the form attribute 118 | * 119 | * @return FormService 120 | */ 121 | public function post(): FormService 122 | { 123 | return $this->method('post'); 124 | } 125 | 126 | /** 127 | * Set put method for the form attribute 128 | * 129 | * @return FormService 130 | */ 131 | public function put(): FormService 132 | { 133 | return $this->method('put'); 134 | } 135 | 136 | /** 137 | * Set patch method for the form attribute 138 | * 139 | * @return FormService 140 | */ 141 | public function patch(): FormService 142 | { 143 | return $this->method('patch'); 144 | } 145 | 146 | /** 147 | * Set delete method for the form attribute 148 | * 149 | * @return FormService 150 | */ 151 | public function delete(): FormService 152 | { 153 | return $this->method('delete'); 154 | } 155 | 156 | /** 157 | * Fill the form values 158 | * 159 | * @param array|object $data 160 | * @return FormService 161 | */ 162 | public function fill($data): FormService 163 | { 164 | return $this->_set('formData', $data); 165 | } 166 | 167 | /** 168 | * Set locale file for inputs translations 169 | * 170 | * @param string $path 171 | * @return FormService 172 | */ 173 | public function locale(string $path): FormService 174 | { 175 | return $this->_set('formLocale', $path); 176 | } 177 | 178 | /** 179 | * Set autocomplete attribute on form, or on individual input fields 180 | * 181 | * @param string $value 182 | * @return FormService 183 | */ 184 | public function autocomplete($value = true): FormService 185 | { 186 | return $this->_set('autocomplete', $value); 187 | } 188 | 189 | /** 190 | * Set inline form style 191 | * 192 | * @param bool $inline 193 | * @return FormService 194 | */ 195 | public function formInline(bool $inline = true): FormService 196 | { 197 | return $this->_set('formInline', $inline); 198 | } 199 | 200 | /** 201 | * Set url for links and form action 202 | * 203 | * @param string $url 204 | * @return FormService 205 | */ 206 | public function url(string $url = null): FormService 207 | { 208 | return $this->_set('url', url($url ?? '')); 209 | } 210 | 211 | /** 212 | * Set route for links and form action 213 | * 214 | * @param string $route 215 | * @param array $params 216 | * @return FormService 217 | */ 218 | public function route(string $route, array $params = []): FormService 219 | { 220 | return $this->_set('url', route($route, $params)); 221 | } 222 | 223 | /** 224 | * Open a fieldset 225 | * 226 | * @param string $legend 227 | * @return FormService 228 | */ 229 | public function fieldsetOpen(string $legend = null): FormService 230 | { 231 | return $this->render('fieldsetOpen')->_set('legend', $legend); 232 | } 233 | 234 | /** 235 | * Close a fieldset 236 | * 237 | * @return FormService 238 | */ 239 | public function fieldsetClose(): FormService 240 | { 241 | return $this->render('fieldsetClose'); 242 | } 243 | 244 | /** 245 | * Set a help text 246 | * 247 | * @param string $text 248 | * @return FormService 249 | */ 250 | public function help(string $text): FormService 251 | { 252 | return $this->_set('help', $text); 253 | } 254 | 255 | /** 256 | * Create a file input 257 | * 258 | * @param string $name 259 | * @param string $label 260 | * @return FormService 261 | */ 262 | public function file(string $name = null, string $label = null): FormService 263 | { 264 | return $this->render('input')->type('file')->name($name)->label($label)->custom()->placeholder('Choose file'); 265 | } 266 | 267 | /** 268 | * Create a text input 269 | * 270 | * @param string $name 271 | * @param string $label 272 | * @param string $default 273 | * @return FormService 274 | */ 275 | public function text(string $name = null, $label = null, string $default = null): FormService 276 | { 277 | return $this->render('input')->type('text')->name($name)->label($label)->value($default); 278 | } 279 | 280 | /** 281 | * Create a date input 282 | * 283 | * @param string $name 284 | * @param string $label 285 | * @param string $default 286 | * @return FormService 287 | */ 288 | public function date(string $name = null, $label = null, string $default = null): FormService 289 | { 290 | return $this->render('input')->type('date')->name($name)->label($label)->value($default); 291 | } 292 | 293 | /** 294 | * Create a time input 295 | * 296 | * @param string $name 297 | * @param string $label 298 | * @param string $default 299 | * @return FormService 300 | */ 301 | public function time(string $name = null, $label = null, string $default = null): FormService 302 | { 303 | return $this->render('input')->type('time')->name($name)->label($label)->value($default); 304 | } 305 | 306 | /** 307 | * Create a telephone input 308 | * 309 | * @param string $name 310 | * @param string $label 311 | * @param string $default 312 | * @return FormService 313 | */ 314 | public function tel(string $name = null, $label = null, string $default = null): FormService 315 | { 316 | return $this->render('input')->type('tel')->name($name)->label($label)->value($default); 317 | } 318 | 319 | /** 320 | * Create a url input 321 | * 322 | * @param string $name 323 | * @param string $label 324 | * @param string $default 325 | * @return FormService 326 | */ 327 | public function urlInput(string $name = null, $label = null, string $default = null): FormService 328 | { 329 | return $this->render('input')->type('url')->name($name)->label($label)->value($default); 330 | } 331 | 332 | /** 333 | * Create a range input 334 | * 335 | * @param string $name 336 | * @param string $label 337 | * @param string $default 338 | * @return FormService 339 | */ 340 | public function range(string $name = null, $label = null, string $default = null): FormService 341 | { 342 | return $this->render('input')->type('range')->name($name)->label($label)->value($default)->custom(); 343 | } 344 | 345 | /** 346 | * Set a minimum value for a field 347 | * 348 | * @param string $value 349 | * @return FormService 350 | */ 351 | public function min($value) 352 | { 353 | return $this->_set('min', $value); 354 | } 355 | 356 | /** 357 | * Set a maximum value for a field 358 | * 359 | * @param string $value 360 | * @return FormService 361 | */ 362 | public function max($value) 363 | { 364 | return $this->_set('max', $value); 365 | } 366 | 367 | /** 368 | * Create a hidden input 369 | * 370 | * @param string $name 371 | * @param string $default 372 | * @return FormService 373 | */ 374 | public function hidden(string $name = null, string $default = null): FormService 375 | { 376 | return $this->render('input')->type('hidden')->name($name)->value($default); 377 | } 378 | 379 | /** 380 | * Create a select input 381 | * 382 | * @param string $name 383 | * @param string $label 384 | * @param array $options 385 | * @param string|array $default 386 | * @return FormService 387 | */ 388 | public function select(string $name = null, string $label = null, $options = [], $default = null): FormService 389 | { 390 | return $this->render('select')->name($name)->label($label)->options($options)->value($default)->custom(); 391 | } 392 | 393 | /** 394 | * Set options for a select field 395 | * 396 | * @param mixed $options 397 | * @param string $valueKey 398 | * @param string $idKey 399 | * @return FormService 400 | */ 401 | public function options($options = [], string $valueKey = null, string $idKey = null): FormService 402 | { 403 | return $this->_set('optionValueKey', $valueKey)->_set('optionIdKey', $idKey)->_set('options', $options); 404 | } 405 | 406 | /** 407 | * Set a multiple select attribute 408 | * 409 | * @param bool $multiple 410 | * @return FormService 411 | */ 412 | public function multiple(bool $status = true): FormService 413 | { 414 | return $this->_set('multiple', $status); 415 | } 416 | 417 | /** 418 | * Create a checkbox input 419 | * 420 | * @param string $name 421 | * @param string $value 422 | * @param string $label 423 | * @param bool $checked 424 | * @return FormService 425 | */ 426 | public function checkbox(string $name = null, string $label = null, string $value = 'on', bool $checked = null): FormService 427 | { 428 | return $this->_radioOrCheckbox('checkbox', $name, $label, $value, $checked); 429 | } 430 | 431 | /** 432 | * Create a radio input 433 | * 434 | * @param string $name 435 | * @param string $value 436 | * @param string $label 437 | * @param bool $checked 438 | * @return FormService 439 | */ 440 | public function radio(string $name = null, string $label = null, string $value = null, bool $checked = null): FormService 441 | { 442 | return $this->_radioOrCheckbox('radio', $name, $label, $value, $checked); 443 | } 444 | 445 | /** 446 | * Create a switch input 447 | * 448 | * @param string $name 449 | * @param string $value 450 | * @param string $label 451 | * @param bool $checked 452 | * @return FormService 453 | */ 454 | public function switch(string $name = null, string $label = null, string $value = null, bool $checked = null): FormService 455 | { 456 | return $this->_radioOrCheckbox('checkbox', $name, $label, $value, $checked)->type('switch'); 457 | } 458 | 459 | /** 460 | * Set inline input style 461 | * @param bool $inline 462 | * @return FormService 463 | */ 464 | public function inline(bool $inline = true): FormService 465 | { 466 | return $this->_set('inline', $inline); 467 | } 468 | 469 | /** 470 | * Create a textarea input 471 | * 472 | * @param string $name 473 | * @param string $label 474 | * @param string $default 475 | * @return FormService 476 | */ 477 | public function textarea(string $name = null, $label = null, string $default = null): FormService 478 | { 479 | return $this->_set('render', 'textarea')->name($name)->label($label)->value($default); 480 | } 481 | 482 | /** 483 | * Set a label 484 | * 485 | * @param string $label 486 | * @return FormService 487 | */ 488 | public function label($label): FormService 489 | { 490 | return $this->_set('label', $label); 491 | } 492 | 493 | /** 494 | * Create a button 495 | * 496 | * @param string $value 497 | * @param string $color 498 | * @param null $size 499 | * @return FormService 500 | */ 501 | public function button(string $value = null, $color = 'primary', $size = null): FormService 502 | { 503 | return $this->type('button')->_set('render', 'button')->value($value)->color($color)->size($size); 504 | } 505 | 506 | /** 507 | * Create a button type submit 508 | * 509 | * @param string $value 510 | * @param string $color 511 | * @param null $size 512 | * @return FormService 513 | */ 514 | public function submit(string $value, $color = 'primary', $size = null): FormService 515 | { 516 | return $this->button($value, $color, $size)->type('submit'); 517 | } 518 | 519 | /** 520 | * Create a button type reset 521 | * 522 | * @param string $value 523 | * @param string $color 524 | * @param null $size 525 | * @return FormService 526 | */ 527 | public function reset(string $value, $color = 'primary', $size = null): FormService 528 | { 529 | return $this->button($value, $color, $size)->type('reset'); 530 | } 531 | 532 | /** 533 | * Create a anchor 534 | * 535 | * @param string $value 536 | * @param string $url 537 | * @return FormService 538 | */ 539 | public function anchor(string $value, $url = null, $color = 'primary', $size = null): FormService 540 | { 541 | return $this->_set('render', 'anchor')->value($value)->url($url)->color($color)->size($size); 542 | } 543 | 544 | /** 545 | * Flag a checkbox or a radio input as checked 546 | * 547 | * @param bool $checked 548 | * @return FormService 549 | */ 550 | public function checked(bool $checked = true): FormService 551 | { 552 | return $this->_set('checked', $checked); 553 | } 554 | 555 | /** 556 | * Set a input value 557 | * 558 | * @param string $value 559 | * @return FormService 560 | */ 561 | public function value($value = null): FormService 562 | { 563 | return $this->_set('value', $value); 564 | } 565 | 566 | /** 567 | * Set a input type 568 | * 569 | * @param string $type 570 | * @return FormService 571 | */ 572 | public function type($type): FormService 573 | { 574 | return $this->_set('type', $type); 575 | } 576 | 577 | /** 578 | * Set a render 579 | * 580 | * @param string $render 581 | * @return FormService 582 | */ 583 | public function render(string $render): FormService 584 | { 585 | return $this->_set('render', $render); 586 | } 587 | 588 | /** 589 | * Set a field id 590 | * 591 | * @param string $id 592 | * @return FormService 593 | */ 594 | public function id($id): FormService 595 | { 596 | return $this->_set('id', $id); 597 | } 598 | 599 | /** 600 | * Set a field name 601 | * 602 | * @param string $name 603 | * @return FormService 604 | */ 605 | public function name($name): FormService 606 | { 607 | return $this->_set('name', $name); 608 | } 609 | 610 | /** 611 | * Set the size 612 | * 613 | * @param string $size 614 | * @return FormService 615 | */ 616 | public function size(string $size = null): FormService 617 | { 618 | return $this->_set('size', $size); 619 | } 620 | 621 | /** 622 | * Set the field as bootstrap custom 623 | * 624 | * @param bool $custom 625 | * @return FormService 626 | */ 627 | public function custom(bool $custom = true): FormService 628 | { 629 | return $this->_set('custom', $custom); 630 | } 631 | 632 | /** 633 | * Set the size as lg 634 | * 635 | * @return FormService 636 | */ 637 | public function lg(): FormService 638 | { 639 | return $this->size('lg'); 640 | } 641 | 642 | /** 643 | * Set the size as sm 644 | * 645 | * @return FormService 646 | */ 647 | public function sm(): FormService 648 | { 649 | return $this->size('sm'); 650 | } 651 | 652 | /** 653 | * Set the color 654 | * 655 | * @param string $color 656 | * @return FormService 657 | */ 658 | public function color(string $color = null): FormService 659 | { 660 | return $this->_set('color', $color); 661 | } 662 | 663 | /** 664 | * Set primary color 665 | * 666 | * @return FormService 667 | */ 668 | public function primary(): FormService 669 | { 670 | return $this->color('primary'); 671 | } 672 | 673 | /** 674 | * Set secondary color 675 | * 676 | * @return FormService 677 | */ 678 | public function secondary(): FormService 679 | { 680 | return $this->color('secondary'); 681 | } 682 | 683 | /** 684 | * Set success color 685 | * 686 | * @return FormService 687 | */ 688 | public function success(): FormService 689 | { 690 | return $this->color('success'); 691 | } 692 | 693 | /** 694 | * Set danger color 695 | * 696 | * @return FormService 697 | */ 698 | public function danger(): FormService 699 | { 700 | return $this->color('danger'); 701 | } 702 | 703 | /** 704 | * Set warning color 705 | * 706 | * @return FormService 707 | */ 708 | public function warning(): FormService 709 | { 710 | return $this->color('warning'); 711 | } 712 | 713 | /** 714 | * Set info color 715 | * 716 | * @return FormService 717 | */ 718 | public function info(): FormService 719 | { 720 | return $this->color('info'); 721 | } 722 | 723 | /** 724 | * Set light color 725 | * 726 | * @return FormService 727 | */ 728 | public function light(): FormService 729 | { 730 | return $this->color('light'); 731 | } 732 | 733 | /** 734 | * Set dark color 735 | * 736 | * @return FormService 737 | */ 738 | public function dark(): FormService 739 | { 740 | return $this->color('dark'); 741 | } 742 | 743 | /** 744 | * Set link style 745 | * 746 | * @return FormService 747 | */ 748 | public function link(): FormService 749 | { 750 | return $this->color('link'); 751 | } 752 | 753 | /** 754 | * Set outline style 755 | * 756 | * @param bool $status 757 | * @return FormService 758 | */ 759 | public function outline(bool $status = true): FormService 760 | { 761 | return $this->_set('outline', $status); 762 | } 763 | 764 | /** 765 | * Set block style 766 | * 767 | * @param bool $status 768 | * @return FormService 769 | */ 770 | public function block(bool $status = true): FormService 771 | { 772 | return $this->_set('block', $status); 773 | } 774 | 775 | /** 776 | * Set readonly style 777 | * 778 | * @param bool $status 779 | * @return FormService 780 | */ 781 | public function readonly($status = true): FormService 782 | { 783 | return $this->_set('readonly', $status); 784 | } 785 | 786 | /** 787 | * Set the input disabled status 788 | * 789 | * @param bool $status 790 | * @return FormService 791 | */ 792 | public function disabled($status = true): FormService 793 | { 794 | return $this->_set('disabled', $status); 795 | } 796 | 797 | /** 798 | * Set the input required status 799 | * 800 | * @param bool $status 801 | * @return FormService 802 | */ 803 | public function required($status = true): FormService 804 | { 805 | return $this->_set('required', $status); 806 | } 807 | 808 | /** 809 | * Set the input placeholder 810 | * 811 | * @param string $placeholder 812 | * @return FormService 813 | */ 814 | public function placeholder($placeholder): FormService 815 | { 816 | return $this->_set('placeholder', $placeholder); 817 | } 818 | 819 | /** 820 | * Set custom attributes for an input 821 | * 822 | * @param array $attrs 823 | * @return FormService 824 | */ 825 | public function attrs(array $attrs = []): FormService 826 | { 827 | return $this->_set('attrs', $attrs); 828 | } 829 | 830 | /** 831 | * Disable input states (valid and invalid classes) and error message 832 | * 833 | * @param string $disable 834 | * @return FormService 835 | */ 836 | public function disableValidation(bool $disable = true): FormService 837 | { 838 | return $this->_set('disableValidation', $disable); 839 | } 840 | 841 | /** 842 | * Set custom attributes for a wrapper input 843 | * 844 | * @param array $attrs 845 | * @return FormService 846 | */ 847 | public function wrapperAttrs(array $attrs = []): FormService 848 | { 849 | return $this->_set('wrapperAttrs', $attrs); 850 | } 851 | 852 | /** 853 | * Create radio or checkbox input 854 | * 855 | * @param string $render 856 | * @param string $name 857 | * @param string $value 858 | * @param string $label 859 | * @param mixed $checked 860 | * @return FormService 861 | */ 862 | private function _radioOrCheckbox($render, $name, $label, $value, $checked): FormService 863 | { 864 | if (is_bool($checked)) { 865 | $this->checked($checked); 866 | } 867 | return $this->_set('render', $render)->name($name)->label($label)->value($value)->custom(); 868 | } 869 | 870 | /** 871 | * Set the size 872 | * 873 | * @param string $size 874 | * @return FormService 875 | */ 876 | private function _set(string $key, $value): FormService 877 | { 878 | $this->_builder->set($key, $value); 879 | return $this; 880 | } 881 | } 882 | --------------------------------------------------------------------------------