diff --git a/README.md b/README.md
index 5cef77c..c1e4581 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
-# Bootstrap 4 forms for Laravel 5
+# Bootstrap 4 forms for Laravel 5/6/7/8
-This is a package for creating Bootstrap 4 styled form elements in Laravel 5.
+[![Latest Version on Packagist][ico-version]][link-packagist]
+[![Total Downloads][ico-downloads]][link-downloads]
+
+This is a package for creating Bootstrap 4 styled form elements in Laravel 5/6.
## Features
@@ -90,7 +93,10 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
```php
// Making all inputs inline
-{!!Form::inlineForm()!!}
+{!!Form::open()->formInline()!!}
+
+// You can use FALSE to turn off disable form inline
+{!!Form::open()->formInline(false)!!}
```
#### Fieldset
@@ -148,10 +154,35 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
{!!Form::select('city', 'Choose your city', [1 => 'Gotham City', 2 => 'Springfield'])!!}
```
-#### Select Default Value
+##### Options
+
+| Param | Type | Default | Description |
+| ---------- | -------- | ------- | ------------- |
+| \$options | iterable | [] | Options list |
+| \$valueKey | string | null | key for value |
+| \$idKey | string | null | key for id |
```php
-{!!Form::select('city', 'Choose your city', [''=>'--choose your city---',1 => 'Gotham City', 2 => 'Springfield'])!!}
+// Example
+
+// With array
+{!!Form::select('city', 'Choose your city')->options([1 => 'Gotham City', 2 => 'Springfield'])!!}
+
+// With collection
+$cities = collect([1 => 'Gotham City', 2 => 'Springfield'])
+{!!Form::select('city', 'Choose your city')->options($cities)!!}
+
+// With model collection
+$cities = \App\City::all();
+{!!Form::select('city', 'Choose your city')->options($cities)!!}
+
+// 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)
+$cities = \App\City::all();
+{!!Form::select('city', 'Choose your city')->options($cities, 'city_name', 'id_object_field')!!}
+
+// 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"
+$cities = \App\City::all();
+{!!Form::select('city', 'Choose your city')->options($cities->prepend('Choose your city', ''))!!}
```
##### Checkbox
@@ -161,7 +192,7 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
| \$name | string | null | Input name |
| \$label | string | null | Input label |
| \$value | string | null | Input value |
-| \$default | boolean | null | Default value |
+| \$checked | boolean | null | Default value |
```php
// Example
@@ -175,7 +206,7 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
| \$name | string | null | Input name |
| \$label | string | null | Input label |
| \$value | string | null | Input value |
-| \$default | boolean | null | Default value |
+| \$checked | boolean | null | Default value |
```php
// Example
@@ -207,6 +238,19 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
{!!Form::date('birthday', 'Birthday')!!}
```
+#### Tel inputs
+
+| Param | Type | Default | Description |
+| --------- | ------ | ------- | ------------- |
+| \$name | string | null | Input name |
+| \$label | string | null | Input label |
+| \$default | string | null | Default value |
+
+```php
+// Example
+{!!Form::tel('number', 'Phone number')!!}
+```
+
#### Time inputs
| Param | Type | Default | Description |
@@ -220,6 +264,19 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
{!!Form::time('hour', 'Meeting hour')!!}
```
+#### URL inputs
+
+| Param | Type | Default | Description |
+| --------- | ------ | ------- | ------------- |
+| \$name | string | null | Input name |
+| \$label | string | null | Input label |
+| \$default | string | null | Default value |
+
+```php
+// Example
+{!!Form::urlInput('website', 'You website')!!}
+```
+
#### Range inputs
| Param | Type | Default | Description |
@@ -292,9 +349,9 @@ If you is using Laravel 5.5, the auto discovery feature will make everything for
### Filling a form
-| Param | Type | Default | Description |
-| ------ | ------ | ------- | ----------- |
-| \$data | object | array | null | DAta fo fill form inputs |
+| Param | Type | Default | Description |
+| ------ | ------------ | ------- | ------------------------ |
+| \$data | object/array | array | Data fo fill form inputs |
```php
// Examples
@@ -334,6 +391,89 @@ Use in anchors and forms openings
{!!Form::anchor("Link via route")->route('home')!!}
```
+### Error Bag
+
+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
+
+| Param | Type | Default | Description |
+| ------- | ------ | ------- | -------------- |
+| \$value | string | null | Error bag name |
+
+```php
+// Example: attach this form to a error bag called "registerErrorBag"
+{!!Form::open()->route('register.post')->errorBag("registerErrorBag")!!}
+
+// ------------------------------------------------------
+
+// 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"
+public function register(Request $request)
+{
+ $validator = Validator::make($request->all(), [
+ // ... rules here
+ ]);
+
+ if ($validator->fails()) {
+ return redirect()
+ ->route('register.form')
+ ->withInput()
+ ->withErrors($validator, 'registerErrorBag');
+ }
+
+ // Proced to register here
+}
+
+// ------------------------------------------------------
+
+// If your validation is on a Form Request, you can add a protected method "$errorBag" to set a ErrorBag name
+
+class RegisterRequest extends FormRequest
+{
+
+ protected $errorBag = 'registerErrorBag';
+
+ public function authorize()
+ {
+ return true;
+ }
+
+ public function rules()
+ {
+ return [
+ // ... rules here
+ ];
+ }
+}
+```
+
+### Errors
+
+Show all errors inside a panel
+
+| Param | Type | Default | Description |
+| ------- | ------ | ------- | ----------- |
+| \$title | string | null | Panel title |
+
+```php
+// Example
+{!!Form::errors("The form has errors")!!}
+```
+
+### Disable validation messages
+
+Disable success/error status and validation error message
+
+| Param | Type | Default | Description |
+| ---------- | ------- | ------- | --------------- |
+| \$disabled | boolean | false | Disabled status |
+
+```php
+// Example
+{!!Form::text('username', 'User name')->disableValidation()!!}
+
+// You can use FALSE to turn off disable validation (to enable it)
+{!!Form::text('username', 'User name')->disableValidation(false)!!}
+```
+
### Checked
Set the checkbox/radio checked status
@@ -361,6 +501,9 @@ Set the checkbox/radio checked status
{!!Form::radio('orange', 'Orange')->inline()!!}
{!!Form::checkbox('orange', 'Orange')->inline()!!}
+
+// You can use FALSE to turn off inline status
+{!!Form::checkbox('orange', 'Orange')->inline(false)!!}
```
### Placeholder
@@ -651,6 +794,32 @@ complete list is in the spec mentioned above.
{!!Form::text('email', 'Your email')->type('email')!!}
```
+### Min
+
+| Param | Type | Default | Description |
+| ------- | ------ | ------- | ------------- |
+| \$value | number | null | Minimum value |
+
+Set min attribute for input
+
+```php
+// Example
+{!!Form::text('age', 'Your age')->type('number')->min(18)!!}
+```
+
+### Max
+
+| Param | Type | Default | Description |
+| ------- | ------ | ------- | ------------- |
+| \$value | number | null | Minimum value |
+
+Set max attribute for input
+
+```php
+// Example
+{!!Form::text('age', 'Your age')->type('number')->max(18)!!}
+```
+
### Name
| Param | Type | Default | Description |
@@ -697,6 +866,19 @@ complete list is in the spec mentioned above.
{!!Form::render('text')->name('age')->label('Your age')!!}
```
+### Disable is-valid CSS Class
+
+| Param | Type | Default | Description |
+| ---------------- | ------- | ------- | -------------------------- |
+| \$disableIsValid | boolean | true | Disable is-valid CSS class |
+
+```php
+// Examples
+
+// Disable Bootstrap's is-valid CSS class
+{!!Form::text('name', 'Name')->disableIsValid()!!}
+```
+
### Chaining properties
You can use chaining feature to use a lot of settings for each component
@@ -714,3 +896,8 @@ You can use chaining feature to use a lot of settings for each component
{!!Form::close()!!}
```
+
+[ico-version]: https://img.shields.io/packagist/v/netojose/laravel-bootstrap-4-forms.svg?style=flat-square
+[ico-downloads]: https://img.shields.io/packagist/dt/netojose/laravel-bootstrap-4-forms.svg?style=flat-square
+[link-packagist]: https://packagist.org/packages/netojose/laravel-bootstrap-4-forms
+[link-downloads]: https://packagist.org/packages/netojose/laravel-bootstrap-4-forms
diff --git a/composer.json b/composer.json
index 787ef31..9819681 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
"email": "sputinykster@gmail.com"
}
],
- "version": "2.0.6",
+ "version": "3.0.5",
"minimum-stability": "dev",
"require": {},
"autoload": {
diff --git a/src/FormBuilder.php b/src/FormBuilder.php
index 40c9b7b..ce7ed23 100644
--- a/src/FormBuilder.php
+++ b/src/FormBuilder.php
@@ -2,1101 +2,552 @@
namespace NetoJose\Bootstrap4Forms;
-class FormBuilder {
-
- /**
- * List of allowed single word
- * values for autocomplete attribute
- *
- * @var array
- */
- private $_allowedAutoComplete;
-
- /**
- * Form input labels locale
- *
- * @var string
- */
- private $_Flocale;
-
- /**
- * Form style
- *
- * @var string
- */
- private $_FformStyle;
-
- /**
- * Form method
- *
- * @var string
- */
- private $_Fmethod;
-
- /**
- * Multipart flag
- *
- * @var boolean
- */
- private $_Fmultipart;
-
- /**
- * Form array data
- *
- * @var array
- */
- private $_Fdata;
-
- /**
- * Inputs id prefix
- * @var string
- */
- private $_FidPrefix;
-
- /**
- * Form autocomplete attribute
- * @var string|null
- */
- private $_Fautocomplete;
-
- /**
- * Input autocomplete attribute
- * @var string|null
- */
- private $_autocomplete;
-
- /**
- * Input meta data
- *
- * @var array
- */
- private $_meta;
-
- /**
- * Input attributes
- *
- * @var array
- */
- private $_attrs;
-
- /**
- * Input wrapper attributes
- *
- * @var array
- */
- private $_wrapperAttrs;
-
- /**
- * Input wrapper flag
- *
- * @var array
- */
- private $_wrapper;
-
- /**
- * Form control type
- *
- * @var string
- */
- private $_type;
-
- /**
- * Form/Link
- *
- * @var string
- */
- private $_url;
-
- /**
- * Input placeholder
- *
- * @var string
- */
- private $_placeholder;
-
- /**
- * Flag to determine checkbox/radio style
- *
- * @var boolean
- */
- private $_checkInline;
-
- /**
- * Input size
- *
- * @var string
- */
- private $_size;
-
- /**
- * Readonly flag
- *
- * @var boolean
- */
- private $_readonly;
-
- /**
- * Disabled flag
- *
- * @var boolean
- */
- private $_disabled;
-
- /**
- * Required flag
- *
- * @var boolean
- */
- private $_required;
-
- /**
- * Input id
- *
- * @var string
- */
- private $_id;
-
- /**
- * Input class
- *
- * @var string
- */
- private $_class;
-
- /**
- * Input name
- *
- * @var string
- */
- private $_name;
-
- /**
- * Input label
- *
- * @var string
- */
- private $_label;
-
- /**
- * Select options
- *
- * @var array
- */
- private $_options;
-
- /**
- * Input help text
- *
- * @var string
- */
- private $_help;
-
- /**
- * Input color
- *
- * @var string
- */
- private $_color;
-
- /**
- * Input outline flag
- *
- * @var boolean
- */
- private $_outline;
-
- /**
- * Input block flag
- *
- * @var boolean
- */
- private $_block;
-
- /**
- * Input value
- *
- * @var boolean
- */
- private $_value;
-
- /**
- * Select multiple flag
- *
- * @var boolean
- */
- private $_multiple;
-
- /**
- * Input prefix
- *
- * @var string
- */
- private $_prefix;
-
- /**
- * Input suffix
- *
- * @var string
- */
- private $_suffix;
-
- public function __construct()
- {
- $this->_resetFlags();
- $this->_resetFormFlags();
-
- //All allowed single word autocomplete values. If the name of input field matches,
- //they will be automatically set as autocomplete value
- //Flip the array to make searches faster
- $this->_allowedAutoComplete = array_flip(['name', 'honorific-prefix', 'given-name', 'additional-name',
- 'family-name', 'honorific-suffix', 'nickname', 'username', 'new-password', 'current-password',
- 'organization-title', 'organization', 'street-address', 'address-line1', 'address-line2', 'address-line3',
- 'address-level4', 'address-level3', 'address-level2', 'address-level1', 'country', 'country-name',
- 'postal-code', 'cc-name', 'cc-given-name', 'cc-additional-name', 'cc-family-name', 'cc-number', 'cc-exp',
- 'cc-exp-month', 'cc-exp-year', 'cc-csc', 'cc-type', 'transaction-currency', 'transaction-amount', 'language',
- 'bday', 'bday-day', 'bday-month', 'bday-year', 'sex', 'url', 'photo', 'tel', 'tel-country-code', 'tel-national',
- 'tel-area-code', 'tel-local', 'tel-local-prefix', 'tel-local-suffix', 'tel-extension', 'email', 'impp']);
- }
+use Illuminate\Support\ViewErrorBag;
+
+class FormBuilder
+{
- /**
- * Set a class attribute
- *
- * @param string $attr
- * @param mixed $value
- */
- public function set(string $attr, $value)
+ private $_attrs = [];
+
+ public function set($key, $value)
{
- $this->{'_' . $attr} = $value;
+ $formatter = 'format' . ucfirst($key);
+ if (method_exists($this, $formatter)) {
+ $value = $this->$formatter($value);
+ }
+ $this->attrs[$key] = $value;
}
- /**
- * Retrieve a class attribute
- *
- * @param string $attr
- * @return mixed
- */
- public function get(string $attr)
+ private function formatMethod($value)
{
- return $this->{'_' . $attr};
+ return strtolower($value);
}
- /**
- * Return a open form tag
- *
- * @return string
- */
- public function open(): string
+ private function formatFormData($value)
{
- $props = [
- 'action' => $this->_url,
- 'method' => $this->_Fmethod === 'get' ? 'get' : 'post'
- ];
-
- if($this->_Fmultipart){
- $props['enctype'] = 'multipart/form-data';
- }
-
- if ($this->_FformStyle === 'inline') {
- $props['class'] = 'form-inline';
- }
-
- if (!is_null($this->_Fautocomplete)) {
- $props['autocomplete'] = $this->_Fautocomplete;
- }
-
- $attrs = $this->_buildAttrs($props, ['class-form-control']);
-
- $ret = '
';
-
- $this->_resetFormFlags();
- $this->_resetFlags();
+ extract($this->get('optionIdKey', 'optionValueKey'));
- return $ret;
- }
-
- /**
- * Return a open fieldset tag
- *
- * @return string
- */
- public function fieldsetOpen(): string
- {
- $this->_class .= ' form-group';
- $attrs = $this->_buildAttrs();
- $ret = '';
+ $render = $this->attrs['render'];
+ $methodName = 'render' . ucfirst($render);
+ $output = $this->$methodName();
+ $this->resetAttributes();
+ return $output;
}
- /**
- * Return a file input tag
- *
- * @return string
- */
- public function file(): string
+ private function renderFormOpen(): string
{
- $attrs = $this->_buildAttrs();
- $id = $this->_getId();
- $placeholder = $this->_placeholder ?: 'Choose file';
+ extract($this->get('id', 'method', 'url', 'formMultipart', 'formInline', 'autocomplete'));
- $input = '';
+ if (!$method) {
+ $method = 'post';
+ }
- return $this->_renderWrapperCommonField($input);
- }
+ $enctype = $formMultipart ? 'multipart/form-data' : null;
- /**
- * Return a text input tag
- *
- * @return string
- */
- public function text(): string
- {
- return $this->_renderInput();
- }
+ $attrs = $this->buildHtmlAttrs([
+ 'method' => in_array($method, ['get', 'post']) ? $method : 'post',
+ 'action' => $url,
+ 'enctype' => $enctype,
+ 'autocomplete' => $autocomplete,
+ 'class' => $formInline ? 'form-inline' : null,
+ 'id' => $id
+ ]);
- /**
- * Return a password input tag
- *
- * @return string
- */
- public function password(): string
- {
- return $this->_renderInput('password');
- }
+ $output = '';
}
- /**
- * Return a email input tag
- *
- * @return string
- */
- public function email(): string
+ private function renderFieldsetOpen(): string
{
- return $this->_renderInput('email');
- }
+ $output = '';
}
- /**
- * Return a hidden input tag
- *
- * @return string
- */
- public function hidden(): string
+ private function renderErrors(): string
{
- $value = $this->_getValue();
- $attrs = $this->_buildAttrs(['value' => $value]);
-
- $this->_resetFlags();
+ $errors = $this->errors()->all();
+ if (count($errors) < 1) {
+ return '';
+ }
- return '';
+ extract($this->get('errorsHeader', 'id'));
+ $attrs = $this->buildHtmlAttrs(['class' => 'alert alert-danger', 'role' => 'alert', 'id' => $id]);
+ $output = '';
+ if ($errorsHeader) {
+ $output .= '' . $this->getText($errorsHeader) . '
';
+ }
+ foreach ($errors as $error) {
+ $output .= '- ' . $error . '
';
+ }
+ return $output . '
';
}
- /**
- * Return a textarea tag
- *
- * @return string
- */
- public function textarea(): string
+ private function renderInput(): string
{
- $attrs = $this->_buildAttrs(['rows' => 3]);
- $value = $this->_getValue();
-
- return $this->_renderWrapperCommonField('');
+ $attributes = $this->getInputAttributes();
+ $attrs = $this->buildHtmlAttrs($attributes);
+ return $this->wrapperInput('');
}
- /**
- * Return a select tag
- *
- * @return string
- */
- public function select(): string
+ private function renderSelect(): string
{
- $attrs = $this->_buildAttrs();
- $value = $this->_getValue();
- $options = '';
-
- if ($this->_multiple) {
- if (!is_array($value)) {
- $value = [$value];
- }
-
- foreach ($this->_options as $key => $label) {
-
- if (array_key_exists($key, $value)) {
- $match = true;
- } else {
- $match = false;
- }
+ extract($this->get('options'));
- $checked = ($match) ? ' selected' : '';
- $options .= '';
- }
- } else {
- foreach ($this->_options as $optvalue => $label) {
- $checked = $optvalue == $value ? ' selected' : '';
- $options .= '';
+ $fieldValue = $this->getValue();
+ $arrValues = is_array($fieldValue) ? $fieldValue : [$fieldValue];
+ $optionsList = '';
+ foreach ($options as $value => $label) {
+ $config = [];
+ if (is_array($label)) {
+ $config = explode(' ', $label['config']);
+ $label = $label['label'];
}
+ $attrs = $this->buildHtmlAttrs([
+ 'value' => $value,
+ 'hidden' => in_array('hidden', $config),
+ 'disabled' => in_array('disabled', $config),
+ 'selected' => in_array(strval($value), $arrValues),
+ ], false);
+ $optionsList .= '';
}
- return $this->_renderWrapperCommonField('');
- }
-
- /**
- * Return a checkbox tag
- *
- * @return string
- */
- public function checkbox(): string
- {
- return $this->_renderCheckboxOrRadio();
+ $attributes = $this->getInputAttributes();
+ $attrs = $this->buildHtmlAttrs($attributes);
+ return $this->wrapperInput('');
}
- /**
- * Return a radio tag
- *
- * @return string
- */
- public function radio(): string
+ private function renderTextarea(): string
{
- return $this->_renderCheckboxOrRadio();
+ $attributes = $this->getInputAttributes();
+ $value = $attributes['value'];
+ unset($attributes['value']);
+ $attrs = $this->buildHtmlAttrs($attributes);
+ return $this->wrapperInput('');
}
- /**
- * Return a button tag
- *
- * @return string
- */
- public function button(): string
+ private function renderCheckbox(): string
{
- return $this->_renderButtonOrAnchor();
+ $attributes = $this->getInputAttributes();
+ $attrs = $this->buildHtmlAttrs($attributes);
+ return $this->wrapperRadioCheckbox('');
}
- /**
- * Return a submit input tag
- *
- * @return string
- */
- public function submit(): string
+ private function renderRadio(): string
{
- return $this->_renderButtonOrAnchor();
+ $attributes = $this->getInputAttributes();
+ $attrs = $this->buildHtmlAttrs($attributes);
+ return $this->wrapperRadioCheckbox('');
}
- /**
- * Return a reset button tag
- *
- * @return string
- */
- public function reset(): string
+ private function renderAnchor(): string
{
- return $this->_renderButtonOrAnchor();
+ extract($this->get('url', 'value'));
+ $class = $this->getBtnAnchorClasses();
+ $attrs = $this->buildHtmlAttrs(['href' => $url, 'class' => $class]);
+ return '' . $value . '';
}
- /**
- * Return a anchor tag
- *
- * @return string
- */
- public function anchor(): string
+ private function renderButton(): string
{
- return $this->_renderButtonOrAnchor();
+ extract($this->get('type', 'value', 'disabled'));
+ $class = $this->getBtnAnchorClasses();
+ $attrs = $this->buildHtmlAttrs(['type' => $type, 'class' => $class, 'disabled' => $disabled]);
+ return '';
}
- /**
- * Return a generic input tag
- *
- * @param string $type
- * @return string
- */
- private function _renderInput($type = 'text'): string
+ private function getBtnAnchorClasses()
{
- $value = $this->_getValue();
- $attrs = $this->_buildAttrs(['value' => $value, 'type' => $type]);
-
- return $this->_renderWrapperCommonField('');
+ extract($this->get('size', 'color', 'outline', 'block', 'type', 'value', 'formInline'));
+ return $this->createAttrsList(
+ 'btn',
+ [$size, 'btn-' . $size],
+ [$color, 'btn-' . ($outline ? 'outline-' : '') . $color],
+ [$block, 'btn-block'],
+ [$formInline, 'mx-sm-2']
+ );
}
- /**
- * Return a button or anchor tag
- *
- * @return string
- */
- private function _renderButtonOrAnchor(): string
+ private function isRadioOrCheckbox(): bool
{
- $size = $this->_size ? ' btn-' . $this->_size : '';
- $outline = $this->_outline ? 'outline-' : '';
- $block = $this->_block ? ' btn-block' : '';
- $disabled = $this->_disabled ? ' disabled' : '';
- $value = $this->_e($this->_value);
- $cls = 'btn btn-' . $outline . $this->_color . $size . $block;
-
- if ($this->_type == 'anchor') {
- $href = $this->_url ?: 'javascript:void(0)';
- $this->_class .= ' ' . $cls . $disabled;
- $attrs = $this->_buildAttrs(
- [
- 'href' => $href,
- 'role' => 'button',
- 'aria-disabled' => $disabled ? 'true' : null
- ], ['class-form-control']
- );
- $ret = '' . $value . '';
- } else {
- $this->_class .= ' ' . $cls;
- $attrs = $this->_buildAttrs(['type' => $this->_type], ['class-form-control']);
- $ret = '';
- }
-
- return $this->_renderWrapperCommonField($ret, true);
+ extract($this->get('render'));
+ return in_array($render, ['checkbox', 'radio']);
}
- /**
- * Return a label tag
- *
- * @return string
- */
- private function _getLabel(): string
+ private function getInputAttributes(): array
{
+ extract($this->get('render', 'type', 'multiple', 'name', 'size', 'placeholder', 'help', 'disabled', 'readonly', 'required', 'autocomplete', 'min', 'max', 'value', 'checked', 'formData', 'disableValidation', 'custom'));
- $label = $this->_label === true ? $this->_name : $this->_label;
- $result = '';
-
- if ($label) {
+ $isRadioOrCheckbox = $this->isRadioOrCheckbox();
+ $type = $isRadioOrCheckbox ? $render : $type;
- $classStr = '';
- if ($this->_FformStyle === 'inline') {
- $classStr = ' class="sr-only"';
- } elseif($this->_FformStyle === 'horizontal') {
- $classStr = ' class="col-sm-2 col-form-label"';
+ $class = 'form-check-input';
+ if($custom){
+ $class = $this->customClass('input');
+ }elseif (!$isRadioOrCheckbox) {
+ $class = 'form-control';
+ switch ($type) {
+ case 'file':
+ $class .= '-file';
+ break;
+ case 'range':
+ $class .= '-range';
+ break;
}
- $id = $this->_getId();
- $result = '';
- }
-
- return $result;
- }
-
- /**
- * Return a string with HTML element attributes
- *
- * @param array $props
- * @param array $ignore
- * @return string
- */
- private function _buildAttrs(array $props = [], array $ignore = []): string
- {
- $props = array_merge($props,
- array_filter($this->_attrs, function($k){
- return $k != 'class';
- }, ARRAY_FILTER_USE_KEY));
-
- if($this->_type){
- $props['type'] = $this->_type;
- }
-
- if($this->_name){
- $props['name'] = $this->_name;
- }
-
- if (!is_null($this->_autocomplete)) {
- $props['autocomplete'] = $this->_autocomplete;
- } else if ($this->_name && isset($this->_allowedAutoComplete[$this->_name])) {
- $props['autocomplete'] = $this->_name;
- }
-
- $id = $this->_getId();
- if($id){
- $props['id'] = $this->_getId();
- }
-
- $props['class'] = $this->_class ?: '';
-
- if ($this->_type == 'select' && $this->_multiple && $this->_name) {
- $props['name'] = $props['name'] . '[]';
- }
-
- if ($this->_placeholder) {
- $props['placeholder'] = $this->_placeholder;
- } elseif($this->_FformStyle === 'inline') {
- $props['placeholder'] = $this->_label;
- }
-
- if ($this->_help) {
- $props['aria-describedby'] = $this->_getIdHelp();
- }
-
- if($this->_required === true) {
- $props['required'] = true;
- }
-
- switch($this->_type) {
- case 'file':
- $formControlClass = ' custom-file-input';
- break;
- case 'range':
- $formControlClass = ' form-control-range';
- break;
- default:
- $formControlClass = ' form-control';
- break;
- }
-
- if (!in_array('class-form-control', $ignore)) {
- $props['class'] .= $formControlClass;
- }
-
- if ($this->_size) {
- $props['class'] .= ' '.$formControlClass.'-' . $this->_size;
- }
-
- if ($this->_FformStyle === 'inline') {
- $props['class'] .= ' mb-2 mr-sm-2';
- }
-
- $props['class'] .= ' ' . $this->_getValidationFieldClass();
-
- if (isset($this->_attrs['class'])) {
- $props['class'] .= ' ' . $this->_attrs['class'];
+ if ($size) {
+ $class .= ' form-control-' . $size;
+ }
}
- $props['class'] = trim($props['class']);
+ $id = $this->getId();
- if(!$props['class']) {
- $props['class'] = false;
+ if (!$disableValidation && $this->errors()->count() > 0) {
+ $class .= $this->errors()->has($name) ? ' is-invalid' : ' is-valid';
}
- if ($this->_type == 'select' && $this->_multiple) {
- $props['multiple'] = true;
- }
+ $attributes = [
+ 'type' => $type,
+ 'name' => $name,
+ 'id' => $id
+ ];
- if ($this->_readonly) {
- $props['readonly'] = true;
+ if ($render !== 'select') {
+ $attributes['value'] = $this->getValue();
+ } else {
+ $attributes['multiple'] = $multiple;
}
- if ($this->_disabled) {
- $props['disabled'] = true;
+ // If the field is a hidden field, we don't need add more attributes
+ if ($type === 'hidden') {
+ return $attributes;
}
- if (in_array($this->_type, ['radio', 'checkbox'])) {
- $value = $this->_getValue();
- if (
- $value && (
- $this->_type === 'checkbox' || $this->_type === 'radio' && $value === $this->_meta['value']
- )
- ) {
- $props['checked'] = true;
+ if ($this->isRadioOrCheckbox()) {
+ if ($this->hasOldInput()) {
+ $isChecked = old($name) === $value;
+ } else {
+ $isChecked = isset($formData[$name]) ? $formData[$name] === $value : $checked;
}
+ $attributes['checked'] = $isChecked;
}
- if ($this->_type == 'hidden') {
- $props['autocomplete'] = false;
- $props['class'] = false;
- }
-
- return $this->_arrayToHtmlAttrs($props);
+ return array_merge($attributes, [
+ 'class' => $class,
+ 'min' => $min,
+ 'max' => $max,
+ 'autocomplete' => $autocomplete,
+ 'placeholder' => $this->getText($placeholder),
+ 'aria-describedby' => $help ? 'help-' . $id : null,
+ 'disabled' => $disabled,
+ 'readonly' => $readonly,
+ 'required' => $required
+ ]);
}
- /**
- * Return a input value
- *
- * @return mixed
- */
- private function _getValue()
+ private function renderLabel(): string
{
- $name = $this->_name;
+ extract($this->get('label', 'formInline', 'render', 'custom'));
- if ($this->_hasOldInput()) {
- return old($name);
+ $class = '';
+ if($custom){
+ $class = $this->customClass('label');
+ } elseif (in_array($render, ['checkbox', 'radio'])){
+ $class = 'form-check-label';
}
- if ($this->_value !== null) {
- return $this->_value;
+ if ($formInline) {
+ $class = join(' ', [$class, 'mx-sm-2']);
}
- if (isset($this->_Fdata[$name])) {
- return $this->_Fdata[$name];
- }
+ $id = $this->getId();
+ $attrs = $this->buildHtmlAttrs([
+ 'for' => $id,
+ 'class' => $class
+ ], false);
+ return '';
}
- /**
- * Check if has a old request
- *
- * @return boolean
- */
- private function _hasOldInput()
+ private function getText($key)
{
- return count((array) old()) != 0;
+ extract($this->get('formLocale'));
+ if ($formLocale) {
+ return __($formLocale . '.' . $key);
+ }
+ return $key;
}
- /**
- * Return a element id
- *
- * @return string
- */
- private function _getId()
+ private function resetAttributes($resetAll = false)
{
- $id = $this->_id;
-
- if (!$id && $this->_name) {
- $id = $this->_name;
- if ($this->_type === 'radio') {
- $id .= '-' . str_slug($this->_meta['value']);
- }
- }
-
- if(!$id) {
- return null;
+ // Remove all attributes
+ if ($resetAll) {
+ $this->attrs = [];
+ return;
}
- return $this->_FidPrefix . $id;
+ // Keep attributes which key starting with 'form'
+ $this->attrs = array_filter($this->attrs, function ($key) {
+ return substr($key, 0, 4) === 'form';
+ }, ARRAY_FILTER_USE_KEY);
}
- /**
- * Return a help text id HTML element
- *
- * @return string
- */
- private function _getIdHelp()
+ private function wrapperInput(string $input): string
{
- $id = $this->_getId();
+ extract($this->get('type', 'help', 'wrapperAttrs', 'formInline', 'name', 'custom'));
- return $id ? 'help-' . $id : '';
- }
+ if ($type === 'hidden') {
+ return $input;
+ }
- /**
- * Return a help text
- *
- * @return string
- */
- private function _getHelpText(): string
- {
- $id = $this->_getIdHelp();
+ $id = $this->getId();
+ $label = $this->renderLabel();
+ $helpText = $help ? '' . $this->getText($help) . '' : '';
+ $error = $this->getInputErrorMarkup($name);
+ $attrs = $wrapperAttrs ?? [];
+ $attrs['class'] = $this->createAttrsList(
+ $custom ? $this->customClass('wrapper') : '',
+ $attrs['class'] ?? null,
+ $formInline ? 'input-group' : 'form-group'
+ );
+ $attributes = $this->buildHtmlAttrs($attrs, false);
- return $this->_help ? '' . $this->_e($this->_help) . '' : '';
+ if($custom && $type === 'file'){
+ $placeholder = $label;
+ $this->set('custom', false);
+ $label = $this->renderLabel();
+ $this->set('custom', true);
+ return '';
+ }else{
+ return '' . $label . $input . $helpText . $error . '
';
+ }
}
- /**
- * Return a prefix id HTML element
- *
- * @return string
- */
- private function _getIdPrefix()
+ private function wrapperRadioCheckbox(string $input): string
{
- $id = $this->_getId();
+ extract($this->get('inline', 'name', 'wrapperAttrs', 'custom'));
- return $id ? 'prefix-' . $id : '';
+ $attrs = $wrapperAttrs ?? [];
+ $attrs['class'] = $this->createAttrsList(
+ $custom ? $this->customClass('wrapper') : 'form-check',
+ [$inline, ($custom ? 'form-check-inline' : 'custom-control-inline')],
+ $attrs['class'] ?? null
+ );
+ $attributes = $this->buildHtmlAttrs($attrs, false);
+ $label = $this->renderLabel();
+ $error = $this->getInputErrorMarkup($name);
+ return '' . $input . $label . $error . '
';
}
- /**
- * Return a prefix
- *
- * @return string
- */
- private function _getPrefix(): string
+ private function getInputErrorMarkup(string $name): string
{
- $id = $this->_getIdPrefix();
+ extract($this->get('disableValidation'));
- return $this->_prefix ? ' ' . $this->_e($this->_prefix) . '
' : '';
- }
-
- /**
- * Return a suffix id HTML element
- *
- * @return string
- */
- private function _getIdSuffix()
- {
- $id = $this->_getId();
+ if ($disableValidation) {
+ return '';
+ }
- return $id ? 'suffix-' . $id : '';
+ $error = $this->errors()->first($name);
+ if (!$error) {
+ return '';
+ }
+ return '' . $this->errors()->first($name) . '
';
}
- /**
- * Return a suffix
- *
- * @return string
- */
- private function _getSuffix(): string
+ private function getId()
{
- $id = $this->_getIdSuffix();
+ extract($this->get('id', 'name', 'formIdPrefix', 'render', 'value'));
- return $this->_suffix ? ' ' . $this->_e($this->_suffix) . '
' : '';
+ if ($id) {
+ return $id;
+ }
+
+ return ($formIdPrefix ?? 'inp-') . $name . ($render === 'radio' ? '-' . $value : '');
}
- /**
- * Return a text with translations, if available
- *
- * @param string $key
- *
- * @return string
- */
- private function _e($key): string
+ private function hasOldInput()
{
- $fieldKey = $key ?: $this->_name;
-
- return $this->_Flocale ? __($this->_Flocale . '.' . $fieldKey) : $fieldKey;
+ return count((array) old()) != 0;
}
- private function _getValidationFieldClass(): string
+ private function getValue()
{
- if (!$this->_name) {
- return '';
+ extract($this->get('name', 'value', 'formData'));
+ if ($this->isRadioOrCheckbox()) {
+ return $value;
}
- if (session('errors') === null) {
- return '';
+ if ($this->hasOldInput()) {
+ if (isset(old()[$name])) {
+ return old($name, $value);
+ }
}
- if ($this->_getValidationFieldMessage()) {
- return ' is-invalid';
- }
+ $fromFill = $formData[$name] ?? null;
- return ' is-valid';
+ return $value ?? $fromFill;
}
- /**
- * Return a checkbox or radio HTML element
- *
- * @return string
- */
- private function _renderCheckboxOrRadio(): string
+ private function buildHtmlAttrs(array $attributes, $appendAttrs = true): string
{
- $this->_class .= ' custom-control-input';
- $attrs = $this->_buildAttrs(["type" => $this->_type, "value" => $this->_meta['value']], ['class-form-control']);
- $inline = $this->_checkInline ? ' form-check-inline' : '';
- $label = $this->_e($this->_label);
- $id = $this->_getId();
- $type = $this->_type;
-
- return $this->_renderWrapperCommonField('', true);
- }
- private function _arrayToHtmlAttrs($attributes){
- return join(' ', array_map(function($key) use ($attributes) {
- $value = $attributes[$key];
- if(is_bool($value)){
- return $value ? $key : '';
- } else {
- return $key.'="'.htmlspecialchars($value).'"';
+ if ($appendAttrs) {
+ extract($this->get('attrs'));
+ $fieldAttrs = $attrs ?? [];
+ $class = $this->createAttrsList($attributes['class'] ?? null, $fieldAttrs['class'] ?? null);
+ if ($class) {
+ $attributes['class'] = $class;
}
+ $attributes = array_merge($fieldAttrs, $attributes);
+ }
+
+ return join(' ', array_filter(
+ array_map(function ($key) use ($attributes) {
+ $value = $attributes[$key];
+ if (is_bool($value)) {
+ return $value ? $key : '';
+ } elseif ($value !== null) {
+ return $key . '="' . htmlspecialchars($value) . '"';
+ }
+ return '';
}, array_keys($attributes))
- );
+ ));
}
- /**
- * Return a input with a wrapper HTML markup
- *
- * @param string $field
- * @param bool $hide_label
- * @return string
- */
- private function _renderWrapperCommonField(string $field, $hide_label = false): string
+ private function customClass(string $element = 'input')
{
- $label = $hide_label ? '' : $this->_getLabel();
- $help = $this->_getHelpText();
- $prefix = $this->_getPrefix();
- $suffix = $this->_getSuffix();
- $error = $this->_getValidationFieldMessage();
-
- $formGroupOpen = $formGroupClose = '';
- if ($this->_wrapper && $this->_FformStyle !== 'inline') {
- $classList = isset($this->_wrapperAttrs['class']) ? $this->_wrapperAttrs['class'] : '';
- $this->_wrapperAttrs['class'] = "form-group " . $classList;
-
- if ($this->_FformStyle === 'horizontal' && !$hide_label) {
- $this->_wrapperAttrs['class'] .= ' row';
- }
-
- $wrapperAttrs = $this->_arrayToHtmlAttrs($this->_wrapperAttrs);
-
- $formGroupOpen = '';
- $formGroupClose = '
';
- }
+ extract($this->get('type', 'size', 'inline', 'render'));
- $inputGroupOpen = $inputGroupClose = '';
+ $type = $type ?? $render;
+ $input = $element === 'input';
+ $wrapper = $element === 'wrapper';
+ $label = $element === 'label';
- if ($this->_wrapper && $this->_FformStyle === 'horizontal' && !$hide_label) {
- $inputGroupOpen .= '';
- $inputGroupClose .= '
';
+ if($input){
+ $class = 'custom-control-input';
+ } elseif($wrapper){
+ $class = 'custom-control' . (isset($inline) && $inline ? ' custom-control-inline' : '');
+ } else {
+ $class = 'custom-control-label';
}
- if ($prefix || $suffix) {
- $inputGroupOpen .= '';
- $inputGroupClose .= '
';
- }
-
- $this->_resetFlags();
-
- return $formGroupOpen . $label . $inputGroupOpen . $prefix . $field . $suffix . $inputGroupClose . $help . $error . $formGroupClose;
+ switch($type){
+ case 'checkbox':
+ if($wrapper){
+ $class .= ' custom-checkbox';
+ }
+ break;
+ case 'radio':
+ if($wrapper){
+ $class .= ' custom-radio';
+ }
+ break;
+ case 'switch':
+ if($wrapper){
+ $class .= ' custom-switch';
+ }
+ break;
+ case 'select':
+ if($input){
+ $class = 'custom-select';
+ $class = $size ? $class . '-' . $size : $class;
+ } elseif($label || $wrapper){
+ $class = '';
+ }
+ break;
+ case 'range':
+ $class = $input ? 'custom-range' : '';
+ break;
+ case 'file':
+ if($wrapper) {
+ $class = 'custom-file';
+ } elseif($input) {
+ $class = 'custom-file-input';
+ } else{
+ $class = 'custom-file-label';
+ }
+ break;
+ default:
+ // do nothing
+ }
+ return $class;
}
- /**
- * Return a validation error message
- *
- * @param string $prefix
- * @param string $sufix
- * @return string|null
- */
- private function _getValidationFieldMessage(string $prefix = '', string $sufix = '
')
+ private function createAttrsList(...$items)
{
- $errors = session('errors');
- if (!$errors) {
- return null;
- }
- $error = $errors->first($this->_name);
-
- if (!$error) {
- return null;
+ $attrs = [];
+ foreach ($items as $item) {
+ if (is_array($item)) {
+ $item = $item[0] ? $item[1] : null;
+ }
+ $attrs[] = $item;
}
-
- return $prefix . $error . $sufix;
+ return join(' ', array_filter($attrs));
}
- /**
- * Reset input flags
- */
- private function _resetFlags()
+ private function errors()
{
- $this->_required = null;
- $this->_wrapper = true;
- $this->_render = null;
- $this->_meta = [];
- $this->_attrs = [];
- $this->_wrapperAttrs = [];
- $this->_type = null;
- $this->_url = null;
- $this->_placeholder = null;
- $this->_checkInline = false;
- $this->_size = null;
- $this->_readonly = false;
- $this->_disabled = false;
- $this->_id = null;
- $this->_name = null;
- $this->_label = null;
- $this->_options = [];
- $this->_help = null;
- $this->_class = null;
- $this->_prefix = null;
- $this->_suffix = null;
- $this->_color = "primary";
- $this->_outline = false;
- $this->_block = false;
- $this->_value = null;
- $this->_multiple = false;
- $this->_autocomplete = null;
+ $errors = session('errors', app(ViewErrorBag::class));
+ extract($this->get('formErrorBag'));
+ if ($formErrorBag) {
+ $errors = $errors->{$formErrorBag};
+ }
+ return $errors;
}
- /**
- * Reset form flags
- */
- private function _resetFormFlags()
+ private function get(...$keys): array
{
-
- $this->_Flocale = null;
- $this->_Fmethod = 'post';
- $this->_Fmultipart = false;
- $this->_FformStyle = 'standard';
- $this->_Fdata = null;
- $this->_FidPrefix = '';
- $this->_Fautocomplete = null;
+ $return = [];
+ foreach ($keys as $key) {
+ $return[$key] = $this->attrs[$key] ?? null;
+ }
+ return $return;
}
-
}
diff --git a/src/FormService.php b/src/FormService.php
index de7d905..22539fd 100644
--- a/src/FormService.php
+++ b/src/FormService.php
@@ -7,28 +7,8 @@
*
* @author neto
*/
-class FormService {
-
- /**
- * The Form builder instance
- *
- * @var FormBuilder
- */
- private $_builder;
-
- /**
- * Render to be used
- *
- * @var string
- */
- private $_render;
-
- /**
- * Allowed renders
- *
- * @var array
- */
- private $_allowedRenders = ['open', 'close', 'fieldsetOpen', 'fieldsetClose', 'file', 'text', 'range', 'password', 'date', 'time', 'email', 'tel', 'url', 'number', 'hidden', 'select', 'checkbox', 'radio', 'textarea', 'button', 'submit', 'anchor', 'reset'];
+class FormService
+{
/**
* Create a new FormSevice instance
@@ -45,16 +25,18 @@ public function __construct()
*/
public function __toString()
{
- $output = '';
-
- if (in_array($this->_render, $this->_allowedRenders)) {
-
- $output = $this->_builder->{$this->_render}();
- }
-
- $this->_render = null;
+ return $this->_builder->render();
+ }
- return $output;
+ /**
+ * Set error bag name
+ *
+ * @param string $value
+ * @return FormService
+ */
+ public function errorBag(string $value = null): FormService
+ {
+ return $this->_set('formErrorBag', $value);
}
/**
@@ -64,7 +46,7 @@ public function __toString()
*/
public function open(): FormService
{
- return $this->render('open');
+ return $this->_set('render', 'formOpen');
}
/**
@@ -74,7 +56,18 @@ public function open(): FormService
*/
public function close(): FormService
{
- return $this->render('close');
+ return $this->_set('render', 'formClose');
+ }
+
+ /**
+ * Show all validation errors
+ *
+ * @param string $title
+ * @return FormService
+ */
+ public function errors(string $title = null): FormService
+ {
+ return $this->_set('render', 'errors')->_set('errorsHeader', $title);
}
/**
@@ -85,7 +78,7 @@ public function close(): FormService
*/
public function idPrefix(string $prefix = ''): FormService
{
- return $this->_set('FidPrefix', $prefix);
+ return $this->_set('formIdPrefix', $prefix);
}
/**
@@ -96,7 +89,7 @@ public function idPrefix(string $prefix = ''): FormService
*/
public function multipart(bool $multipart = true): FormService
{
- return $this->_set('Fmultipart', $multipart);
+ return $this->_set('formMultipart', $multipart);
}
/**
@@ -107,7 +100,7 @@ public function multipart(bool $multipart = true): FormService
*/
public function method(string $method): FormService
{
- return $this->_set('Fmethod', $method);
+ return $this->_set('method', $method);
}
/**
@@ -168,16 +161,7 @@ public function delete(): FormService
*/
public function fill($data): FormService
{
-
- if (method_exists($data, 'toArray')) {
- $data = $data->toArray();
- }
-
- if (!is_array($data)) {
- $data = [];
- }
-
- return $this->_set('Fdata', $data);
+ return $this->_set('formData', $data);
}
/**
@@ -188,74 +172,29 @@ public function fill($data): FormService
*/
public function locale(string $path): FormService
{
- return $this->_set('Flocale', $path);
- }
-
- /**
- * Set inline form to inline inputs
- * @param bool $inline
- * @return FormService
- */
- public function inlineForm(bool $inline = true): FormService
- {
- if($inline) {
- return $this->_set('FformStyle', 'inline');
- }else{
- return $this;
- }
- }
-
- /**
- * @param bool $wrapper
- * @return FormService
- */
- public function noWrapper(bool $wrapper = false)
- {
- return $this->_set('wrapper', $wrapper);
- }
-
- /**
- * Set horizontal form
- * @param bool $horizontal
- * @return FormService
- */
- public function horizontalForm(bool $horizontal = true): FormService
- {
- if($horizontal) {
- return $this->_set('FformStyle', 'horizontal');
- }else{
- return $this;
- }
+ return $this->_set('formLocale', $path);
}
/**
- * Set autocomplete value ('on', 'off', or one of the permitted values)
- *
- * If set on the form, only 'on' or 'off' are valid and are inherited by input fields.
- * The inherited value can be overridden on individual input fields
- *
- * See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
+ * Set autocomplete attribute on form, or on individual input fields
*
* @param string $value
* @return FormService
*/
- public function autocomplete(string $value = 'on'): FormService
+ public function autocomplete($value = true): FormService
{
- if ($this->_render == "open") {
- return $this->_set('Fautocomplete', $value);
- }
-
return $this->_set('autocomplete', $value);
}
/**
- * Set inline style for checkbox and radio inputs
+ * Set inline form style
+ *
* @param bool $inline
* @return FormService
*/
- public function inline(bool $inline = true): FormService
+ public function formInline(bool $inline = true): FormService
{
- return $this->_set('checkInline', $inline);
+ return $this->_set('formInline', $inline);
}
/**
@@ -264,9 +203,9 @@ public function inline(bool $inline = true): FormService
* @param string $url
* @return FormService
*/
- public function url(https://github.com/string%20$url): FormService
+ public function url(https://github.com/string%20$url%20=%20null): FormService
{
- return $this->_set('url', url(https://github.com/$url));
+ return $this->_set('url', url(https://github.com/$url%20??%20%27'));
}
/**
@@ -289,7 +228,7 @@ public function route(string $route, array $params = []): FormService
*/
public function fieldsetOpen(string $legend = null): FormService
{
- return $this->_set('meta', ['legend' => $legend])->render('fieldsetOpen');
+ return $this->render('fieldsetOpen')->_set('legend', $legend);
}
/**
@@ -322,7 +261,7 @@ public function help(string $text): FormService
*/
public function file(string $name = null, string $label = null): FormService
{
- return $this->name($name)->label($label)->type('file');
+ return $this->render('input')->type('file')->name($name)->label($label)->custom()->placeholder('Choose file');
}
/**
@@ -335,7 +274,7 @@ public function file(string $name = null, string $label = null): FormService
*/
public function text(string $name = null, $label = null, string $default = null): FormService
{
- return $this->type('text')->name($name)->label($label)->value($default);
+ return $this->render('input')->type('text')->name($name)->label($label)->value($default);
}
/**
@@ -348,7 +287,7 @@ public function text(string $name = null, $label = null, string $default = null)
*/
public function date(string $name = null, $label = null, string $default = null): FormService
{
- return $this->type('date')->name($name)->label($label)->value($default);
+ return $this->render('input')->type('date')->name($name)->label($label)->value($default);
}
/**
@@ -361,7 +300,33 @@ public function date(string $name = null, $label = null, string $default = null)
*/
public function time(string $name = null, $label = null, string $default = null): FormService
{
- return $this->type('time')->name($name)->label($label)->value($default);
+ return $this->render('input')->type('time')->name($name)->label($label)->value($default);
+ }
+
+ /**
+ * Create a telephone input
+ *
+ * @param string $name
+ * @param string $label
+ * @param string $default
+ * @return FormService
+ */
+ public function tel(string $name = null, $label = null, string $default = null): FormService
+ {
+ return $this->render('input')->type('tel')->name($name)->label($label)->value($default);
+ }
+
+ /**
+ * Create a url input
+ *
+ * @param string $name
+ * @param string $label
+ * @param string $default
+ * @return FormService
+ */
+ public function urlInput(string $name = null, $label = null, string $default = null): FormService
+ {
+ return $this->render('input')->type('url')->name($name)->label($label)->value($default);
}
/**
@@ -374,7 +339,29 @@ public function time(string $name = null, $label = null, string $default = null)
*/
public function range(string $name = null, $label = null, string $default = null): FormService
{
- return $this->type('range')->name($name)->label($label)->value($default);
+ return $this->render('input')->type('range')->name($name)->label($label)->value($default)->custom();
+ }
+
+ /**
+ * Set a minimum value for a field
+ *
+ * @param string $value
+ * @return FormService
+ */
+ public function min($value)
+ {
+ return $this->_set('min', $value);
+ }
+
+ /**
+ * Set a maximum value for a field
+ *
+ * @param string $value
+ * @return FormService
+ */
+ public function max($value)
+ {
+ return $this->_set('max', $value);
}
/**
@@ -386,7 +373,7 @@ public function range(string $name = null, $label = null, string $default = null
*/
public function hidden(string $name = null, string $default = null): FormService
{
- return $this->name($name)->value($default)->type('hidden');
+ return $this->render('input')->type('hidden')->name($name)->value($default);
}
/**
@@ -400,47 +387,83 @@ public function hidden(string $name = null, string $default = null): FormService
*/
public function select(string $name = null, string $label = null, $options = [], $default = null): FormService
{
- return $this->name($name)->label($label)->options($options)->value($default)->type('select');
+ return $this->render('select')->name($name)->label($label)->options($options)->value($default)->custom();
}
/**
* Set options for a select field
*
- * @param array $options
+ * @param mixed $options
+ * @param string $valueKey
+ * @param string $idKey
+ * @return FormService
+ */
+ public function options($options = [], string $valueKey = null, string $idKey = null): FormService
+ {
+ return $this->_set('optionValueKey', $valueKey)->_set('optionIdKey', $idKey)->_set('options', $options);
+ }
+
+ /**
+ * Set a multiple select attribute
+ *
+ * @param bool $multiple
* @return FormService
*/
- public function options(array $options = []): FormService
+ public function multiple(bool $status = true): FormService
{
- $items = is_iterable($options) ? $options : [0 => 'Must be iterable'];
- return $this->_set('options', $items);
+ return $this->_set('multiple', $status);
}
/**
* Create a checkbox input
*
* @param string $name
- * @param string $label
* @param string $value
- * @param string $default
+ * @param string $label
+ * @param bool $checked
* @return FormService
*/
- public function checkbox(string $name = null, string $label = null, string $value = null, string $default = null): FormService
+ public function checkbox(string $name = null, string $label = null, string $value = 'on', bool $checked = null): FormService
{
- return $this->_checkboxRadio('checkbox', $name, $label, $value, $default);
+ return $this->_radioOrCheckbox('checkbox', $name, $label, $value, $checked);
}
/**
* Create a radio input
*
* @param string $name
- * @param string $label
* @param string $value
- * @param string $default
+ * @param string $label
+ * @param bool $checked
* @return FormService
*/
- public function radio(string $name = null, string $label = null, string $value = null, string $default = null): FormService
+ public function radio(string $name = null, string $label = null, string $value = null, bool $checked = null): FormService
{
- return $this->_checkboxRadio('radio', $name, $label, $value, $default);
+ return $this->_radioOrCheckbox('radio', $name, $label, $value, $checked);
+ }
+
+ /**
+ * Create a switch input
+ *
+ * @param string $name
+ * @param string $value
+ * @param string $label
+ * @param bool $checked
+ * @return FormService
+ */
+ public function switch(string $name = null, string $label = null, string $value = null, bool $checked = null): FormService
+ {
+ return $this->_radioOrCheckbox('checkbox', $name, $label, $value, $checked)->type('switch');
+ }
+
+ /**
+ * Set inline input style
+ * @param bool $inline
+ * @return FormService
+ */
+ public function inline(bool $inline = true): FormService
+ {
+ return $this->_set('inline', $inline);
}
/**
@@ -453,7 +476,7 @@ public function radio(string $name = null, string $label = null, string $value =
*/
public function textarea(string $name = null, $label = null, string $default = null): FormService
{
- return $this->type('textarea')->name($name)->value($default)->label($label);
+ return $this->_set('render', 'textarea')->name($name)->label($label)->value($default);
}
/**
@@ -477,7 +500,7 @@ public function label($label): FormService
*/
public function button(string $value = null, $color = 'primary', $size = null): FormService
{
- return $this->type('button')->color($color)->size($size)->value($value);
+ return $this->type('button')->_set('render', 'button')->value($value)->color($color)->size($size);
}
/**
@@ -490,7 +513,7 @@ public function button(string $value = null, $color = 'primary', $size = null):
*/
public function submit(string $value, $color = 'primary', $size = null): FormService
{
- return $this->button($value)->type('submit')->color($color)->size($size);
+ return $this->button($value, $color, $size)->type('submit');
}
/**
@@ -503,7 +526,7 @@ public function submit(string $value, $color = 'primary', $size = null): FormSer
*/
public function reset(string $value, $color = 'primary', $size = null): FormService
{
- return $this->button($value)->type('reset')->color($color)->size($size);
+ return $this->button($value, $color, $size)->type('reset');
}
/**
@@ -513,13 +536,9 @@ public function reset(string $value, $color = 'primary', $size = null): FormServ
* @param string $url
* @return FormService
*/
- public function anchor(string $value, $url = null): FormService
+ public function anchor(string $value, $url = null, $color = 'primary', $size = null): FormService
{
- if ($url) {
- $this->url(https://github.com/$url);
- }
-
- return $this->button($value)->type('anchor');
+ return $this->_set('render', 'anchor')->value($value)->url(https://github.com/$url)->color($color)->size($size);
}
/**
@@ -530,14 +549,7 @@ public function anchor(string $value, $url = null): FormService
*/
public function checked(bool $checked = true): FormService
{
- $type = $this->_builder->get('type');
- $meta = $this->_builder->get('meta');
-
- if ($type === 'radio' && $checked) {
- $checked = $meta['value'];
- }
-
- return $this->value($checked);
+ return $this->_set('checked', $checked);
}
/**
@@ -548,11 +560,7 @@ public function checked(bool $checked = true): FormService
*/
public function value($value = null): FormService
{
- if ($value !== null) {
- return $this->_set('value', $value);
- }
-
- return $this;
+ return $this->_set('value', $value);
}
/**
@@ -563,7 +571,7 @@ public function value($value = null): FormService
*/
public function type($type): FormService
{
- return $this->_set('type', $type)->render($type);
+ return $this->_set('type', $type);
}
/**
@@ -574,9 +582,7 @@ public function type($type): FormService
*/
public function render(string $render): FormService
{
- $this->_render = $render;
-
- return $this;
+ return $this->_set('render', $render);
}
/**
@@ -590,17 +596,6 @@ public function id($id): FormService
return $this->_set('id', $id);
}
- /**
- * Set a field class
- *
- * @param string $class
- * @return FormService
- */
- public function class($class): FormService
- {
- return $this->_set('class', $class);
- }
-
/**
* Set a field name
*
@@ -623,6 +618,17 @@ public function size(string $size = null): FormService
return $this->_set('size', $size);
}
+ /**
+ * Set the field as bootstrap custom
+ *
+ * @param bool $custom
+ * @return FormService
+ */
+ public function custom(bool $custom = true): FormService
+ {
+ return $this->_set('custom', $custom);
+ }
+
/**
* Set the size as lg
*
@@ -747,12 +753,12 @@ public function link(): FormService
/**
* Set outline style
*
- * @param bool $outline
+ * @param bool $status
* @return FormService
*/
- public function outline(bool $outline = true): FormService
+ public function outline(bool $status = true): FormService
{
- return $this->_set('outline', $outline);
+ return $this->_set('outline', $status);
}
/**
@@ -761,7 +767,7 @@ public function outline(bool $outline = true): FormService
* @param bool $status
* @return FormService
*/
- public function block(bool $status= true): FormService
+ public function block(bool $status = true): FormService
{
return $this->_set('block', $status);
}
@@ -794,7 +800,7 @@ public function disabled($status = true): FormService
* @param bool $status
* @return FormService
*/
- public function required($status = true) : FormService
+ public function required($status = true): FormService
{
return $this->_set('required', $status);
}
@@ -822,82 +828,54 @@ public function attrs(array $attrs = []): FormService
}
/**
- * Set custom attributes for a wrapper input
+ * Disable input states (valid and invalid classes) and error message
*
- * @param array $attrs
+ * @param string $disable
* @return FormService
*/
- public function wrapperAttrs(array $attrs = []): FormService
+ public function disableValidation(bool $disable = true): FormService
{
- return $this->_set('wrapperAttrs', $attrs);
+ return $this->_set('disableValidation', $disable);
}
/**
- * Set a multiple select attribute
- *
- * @param bool $multiple
- * @return FormService
- */
- public function multiple(bool $multiple = true): FormService
- {
- return $this->_set('multiple', $multiple);
- }
-
- /**
- * Set input group prefix
+ * Set custom attributes for a wrapper input
*
- * @param string $prefix
+ * @param array $attrs
* @return FormService
*/
- public function prefix(string $prefix): FormService
+ public function wrapperAttrs(array $attrs = []): FormService
{
- return $this->_set('prefix', $prefix);
+ return $this->_set('wrapperAttrs', $attrs);
}
/**
- * Set input group suffix
+ * Create radio or checkbox input
*
- * @param string $suffix
+ * @param string $render
+ * @param string $name
+ * @param string $value
+ * @param string $label
+ * @param mixed $checked
* @return FormService
*/
- public function suffix(string $suffix): FormService
+ private function _radioOrCheckbox($render, $name, $label, $value, $checked): FormService
{
- return $this->_set('suffix', $suffix);
+ if (is_bool($checked)) {
+ $this->checked($checked);
+ }
+ return $this->_set('render', $render)->name($name)->label($label)->value($value)->custom();
}
/**
- * Set a form builder attribute
+ * Set the size
*
- * @param string $attr
- * @param mixed $value
+ * @param string $size
* @return FormService
*/
- private function _set($attr, $value): FormService
+ private function _set(string $key, $value): FormService
{
- $this->_builder->set($attr, $value);
-
+ $this->_builder->set($key, $value);
return $this;
}
-
- /**
- * Render a checkbox or a radio input
- *
- * @param string $type
- * @param string $name
- * @param string $label
- * @param mixed $value
- * @param string $default
- * @return FormService
- */
- private function _checkboxRadio($type, $name, $label, $value, $default): FormService
- {
- $inputValue = $value === null ? $name : $value;
-
- if ($default) {
- $default = $inputValue;
- }
-
- return $this->_set('meta', ['value' => $inputValue])->type($type)->name($name)->label($label)->value($default);
- }
-
}