Skip to content

Commit

Permalink
1.0.0-alpha Tidy, Concernify, Direct Render
Browse files Browse the repository at this point in the history
  • Loading branch information
Corbin committed Apr 30, 2021
1 parent 742cd52 commit 572a58e
Show file tree
Hide file tree
Showing 15 changed files with 939 additions and 468 deletions.
113 changes: 77 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,27 @@ Created for personal use, and is not well documented or tidy. Feel free to use /

QForm for Laravel does a bunch of html form stuff, making use of Laravel components
- Create most types of html inputs with a single component
- Make use of the QForm::init() set of tools either by itself or with a component to easily access a models data, create form name attributes with prefix etc, and deal with error display and old() for you.
- Make use of the QForm::new() set of tools either by itself or with a component to easily access a models data, create form name attributes with prefix etc, and deal with error display and old() for you.
- Customize template
- In the provided base Bootstrap 4 template, it makes some attempts to provide labelling, error and other accesibility features.
```php
$form = Qform::new()->model(User::first())->text('forms.edit_user');
```
```html
{{ $form->input('name')->render(['type' => 'text']) }}
{{ $form->input('email')->render(['type' => 'email']) }}
{{ $form->input('level')->render(['type' => 'select', 'variables' => [0 => 'User', '1' => 'Admin']]) }}
```

- The input will automatically look for errors and old values based on value given by input()
- The input will look to array or model given by model() to get input value
- The input will automatically look to the given text for input label and guide text, eg. text('forms.edit_user') as above, in the case of input('name') will look to 'forms.edit_user.name' for the translation. Or if you give a table via table() such as table('users') it will look to 'columns.users.name'. It looks for text first, then table. You may also pass an array of key to text to text().


## Warnings
1. Doesn't play nice when array inputs such as select have muliple options that resolve to false (not strict)

2. QForm::init() expects that you will have your translations arranged in a certain way, using key translations,
2. QForm::new() expects that you will have your translations arranged in a certain way, using key translations,
a columns.php translation file arranged with table name as key and array of column names as follows
```php
'users' => [
Expand Down Expand Up @@ -46,11 +59,15 @@ and a forms.php (or any name you choose, this is optional) arranged in the same
... Other forms
```

For example you have a signup form and a login form. Preparing a QForm via `$form = QForm::init(NULL, 'forms.login')->table('users')` means it will first look to forms.login for the column text, then columns.users.
For example you have a signup form and a login form. Preparing a QForm via `$form = QForm::new()->text('forms.login')->table('users')` means it will first look to forms.login for the column text, then columns.users.



# Setup
## Composer

composer require corbinjurgens/qform

## Manual Installation

Copy the following to main composer.(in the case that the package is added to packages/corbinjurgens/qform)
Expand Down Expand Up @@ -112,78 +129,102 @@ Array input, ie. anything that has, or can have multiple options

Using components with the QForm tools is the intended usage of this package

### Basics

In your template or controller, create a form. See the warning section above for an example of the translation files that this would be pointing to
```html
@php
// Initiate the $form either in your template, or from the controller
// To edit an item, pass a model as the first parameter, or if your form will never edit, just pass null. Personally I usually share form between create and edit and pass a new model when creating
// For second parameter point to a translation, pass an array of translations, or leave it empty. Pass table with ->table() to point to a table in tables.php translation file
$form = QForm::init($user, 'forms.permissions')->table('users');
// To edit an item, pass a model as the via model(), or if your form will never edit, just pass null or do not call. Personally I usually share form between create and edit and pass a new model when creating
// For text() point to a translation, pass an array of translations, or leave it empty. Pass table with ->table() to point to a table in tables.php translation file
$form = QForm::new()->model($user)->text('forms.permissions')->table('users');
@endphp

{{-- Shift current column to 'name' and pass it to the form. The form will automatically look to the model for the 'name' value and fill the input, and look to translation files first for forms.permissions.name, then users.name --}}
<x-qform-input type="text" :form="$form->input('name')" />
`<x-qform-input type="text" :form="$form->input('name')" />`
{{-- Or --}}
{{ $form->input('name')->render(['type' => 'text']) }}

@php( $form->input('level') )
{{-- In the previous input, I shifted current input as I passed it to :form, but you can also shift separately, then access.
Normally, $form->text() would look for the current inputs text, so first it would look to forms.permissions.level, then users.level. But because I passed a value to it, its looking to the same root, just different key to get :variables (See Introduction section for example of translation files)
Normally, $form->getText() would look for the current inputs text, so first it would look to forms.permissions.level, then users.level. But because I passed a value to it, its looking to the same root, just different key to get :variables (See Introduction section for example of translation files)
--}}
<x-qform-input type="radio" :form="$form" :variables="$form->text('levels')"/>


<x-qform-input type="radio" :form="$form" :variables="$form->getText('levels')"/>
{{-- Or --}}
{{ $form->render(['variables' => $form->getText('levels'), 'type' => 'radio']) }}



{{--
Normally this would look to forms.permissions.notifications, then users.notifications,
but by passing a translation pointer, or array of columns to text_shift() I am telling it to look elsewhere for the 'notifications' text (and guide text)
WARNING: text_shift() and value_shift() functions persist between input shifts so you must either pass null again, or call hard_reset() to clear
but by passing a translation pointer, or array of columns to textShift() I am telling it to look elsewhere for the 'notifications' text (and guide text)
WARNING: textShift() and dataShift() functions persist between input shifts so you must either pass null again, or call hardReset() to clear
--}}
<x-qform-input type="checkbox" :form="$form->input('notifications')->text_shift('forms.admin')"/>
<x-qform-input type="checkbox" :form="$form->input('notifications')->textShift('forms.admin')"/>
{{-- Or --}}
{{ $form->input('notifications')->textShift('forms.admin')->render(['type' => 'checkbox']) }}
```

## Freely

You can use QForm tools without using a component. This makes creating your inputs id, name and value easy, saving you a lot of repition

```html
@php( $form = QForm::new()->model($user)->text('forms.permissions')->table('users') )

@php( $form->input('name') )
<label for="{{ $form->getId() }}">{{ $form->getText() }}<label>
<p>{{ $form->getGuide() }}</p>
<p>{{ $form->getError() }}</p>
<input type="text" value="{{ $form->getValue() }}" name="{{ $form->getName() }}" id="{{ $form->getId() }}" />

```

### Other functions
## Other functions

Use the prefix function and pass an array (or null to clear), and it will automatically prefix the inputs name attribute
WARNING prefix persists between input shifts, so you must clear it by passing null or calling hard_reset().
Be sure in situuations where you shift the input and also get some other value that depends on the input, that you set the input first, or set it separately. However, in this example it wouldn't matter even if the input wasn't shifted yet
```html
@php
$form = QForm::init($user, 'forms.permissions')->table('users');
$form = QForm::new()->model($user)->text('forms.permissions')->table('users');
@endphp
<x-qform-input type="radio" :form="$form->input('level')->prefix(['admin', 'data'])" :variables="$form->text('levels')"/>
<x-qform-input type="radio" :form="$form->input('level')->prefix(['admin', 'data'])" :variables="$form->getText('levels')"/>
{{-- the inputs name attribute will be name="admin[data][level]" --}}
{{-- Or --}}
{{ $form->input('level')->prefix(['admin', 'data'])->render(['type' => 'radio', 'variables' => $form->getText('levels')]) }}
```

You can also use prefixIn() and prefixOut() to add a set of prefixes, and then after back out again

```html

*The following are functions that are set for each input and are cleared when shifting input:*

Call required($required = true) to make the current input required
{{ $form->input('name')->prefixIn(['admin', 'data'])->render(['type' => 'text']) }}
{{-- name will be name="admin[data][name]" --}}

Call set_name($name = null) to set a string name if it is different than the column as passed via input()
{{ $form->input('address')->render(['type' => 'text']) }}
{{-- name will be name="admin[data][address]" as prefix is retained between inputs--}}

Call default($value = null) to set a value for when the model is null or doesn't exist
{{ $form->input('email')->prefixIn(['preferences'])->render(['type' => 'text']) }}
{{-- name will be name="admin[data][preferences][email]" --}}

Call set_text($text, $guide = null) and pass the form label text, and optionally form guide text. This will use the passed string as is
{{ $form->input('dob')->prefixOut()->render(['type' => 'text']) }}
{{-- name will be name="admin[data][dob]" so we have gone back to the previous prefix config --}}
```

Call alt_text($key) to look to the same translation file passed, but just look for a different column
*The following are functions that are set for each input and are cleared when shifting input:*

Call alt_text_base($base) and pass an array, or a string pointing to translation path to shift where the text will be found. This is similar to shift_text() but does not persist between inputs
Call required($required = true) to make the current input required

## Freely
Call name($name = null) to set a string name if it is different than the column as passed via input()

You can use QForm tools without using a component. This makes creating your inputs id, name and value easy, saving you a lot of repition
Call default($value = null) to set a value for when the model is null or doesn't exist

```html
@php( $form = QForm::init($user, 'forms.permissions')->table('users') )
Call setText($text, $guide = null) and pass the form label text, and optionally form guide text. This will use the passed string as is

@php( $form->input('name') )
<label for="{{ $form->id() }}">{{ $form->text() }}<label>
<p>{{ $form->guide() }}</p>
<p>{{ $form->error() }}</p>
<input type="text" value="{{ $form->value() }}" name="{{ $form->name() }}" id="{{ $form->id() }}" />
Call altText($key) to look to the same translation file passed, but just look for a different column

```
Call altTextBase($base) and pass an array, or a string pointing to translation path to shift where the text will be found. This is similar to shiftText() but does not persist between inputs

# Customize template

Expand All @@ -208,5 +249,5 @@ This code is untested and not to any standard. It has however been used extensiv

## TODO
- PHPDocs would be nice but not important while I don't expect anyone else to use this code
- QForm functions are a bit all over the place (the function names aren't clear whether it is setting or getting)
- DONE getting always starts with get, and class is split into traits: QForm functions are a bit all over the place (the function names aren't clear whether it is setting or getting)
- Untested in a fresh enviroment. I may have accidentally used a local function or other one of my private packages without realizing
101 changes: 101 additions & 0 deletions src/Concerns/Build.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace Corbinjurgens\QForm\Concerns;

use Corbinjurgens\QForm\ServiceProvider as S;

use Illuminate\Support\ViewErrorBag;

trait Build
{

/** @var bool */
protected $array_type = false;

/**
* When the error should return array as https://laravel.com/docs/8.x/validation#retrieving-all-error-messages-for-a-field
* For example when using a multi dimentional form
*
* @param bool $array_type
*/
public function arrayType($array_type = false){
$this->array_type = $array_type;
return $this;
}

/** @var ViewErrorBag */
protected $errors = NULL;

/**
* Load errors from session, if empty set as an empty Error Bag
* In the same way template $errors variable works
*
*
*/
protected function loadErrors(){
$this->errors = session()->get('errors', app(ViewErrorBag::class));
}

/**
* Points to the input key, or in other words database column.
* By default it is also used for ->id() and ->name()
*
* @var string
*/
protected $key = NULL;


/**
* String points to translation file, defaulting to forms.php, it will look for input $key in that file.
* You can instead give other file or more deeper like forms.signup and it will look for key inside there
* If you use an array, text and guide will look for the key from there instead
* When paried with function guide() you can separate out the text and guide
*
* @var null|string|array
*/
protected $text = NULL;

/**
* Set text used for the form.
* Can be an array of translations, or a string pointing to where in your key translations the text is found
*
* @param null|string|array $text
*/
public function text($text = null){
$this->text = $text;
return $this;
}

/**
* By default, function guide() will look to trans or array of $text with '_guide' appended to $key
* Instead you can add either guides array, or string to translaton path to search directly within that
* without '_guide' suffix
*
* @param null|string|array $guides
*/
protected $guides = null;

public function guides($guides = []){
$this->guides = $guides;
return $this;
}

/** @var string|null */
protected $table = null;

/**
* Set forms table
* If key is not found in $text and $table has been set,
* It will look to the columns.php file for the table, and key eg
* __('columns.user.password')
* This is a great way to specify only the columns that are different via $text such as 'forms.signup',
* and for the rest use shared values found in columns table such as table('users')
*
* @param null|string $table
*/
public function table(string $table = null){
$this->table = $table;
return $this;
}

}
Loading

0 comments on commit 572a58e

Please sign in to comment.