Skip to content
Merged

V1.4 #113

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Form supports all of the default Nette inputs and adds new ones
+ `addMultiWhisperer()` - same as whisperer, more options can be selected
+ `addDuplicator()` - container which can be duplicated many times
+ `addDependentSelect()` - select box that can change options via ajax based on change of another input(s)
+ `addDependentMultiSelect()` - same as DependantSelect, but more options can be selected
+ `addDependentMultiSelect()` - same as DependentSelect, but more options can be selected
+ `addDate()` - date input, can limit min and max date

## Custom settings
Expand All @@ -41,6 +41,7 @@ Form supports all of the default Nette inputs and adds new ones
+ `addBox()` - all inputs added after this call will render in new card
+ `setFloatingLabel()` - inputs will be rendered with [floating labels](https://getbootstrap.com/docs/5.0/forms/floating-labels/)
+ `setRenderInline()` - label and input are rendered each in separate row
+ `setButtonClass()` - default CSS class for all form buttons (e.g. `rounded rounded-4`); can be overridden by `setClass()` on individual buttons
+ `setRenderManually()` - set manual render, template with same name as form is used (eg. file `MyForm.php` -> `myForm.latte`)

### Groups
Expand All @@ -51,28 +52,29 @@ Inputs are rendered in `card-body` div
Submitters, links and buttons in `card-footer`

### Container
Container works as standard Nette Continer and has these new features
Container works as standard Nette Container and has these new features

+ `setId()` - add html id to outer div of container
+ `showCard()` - show container as BS5 [card](https://getbootstrap.com/docs/5.0/components/card/)
+ `setTitle()` - show title of container (only works when container is rendered as card)
+ `setColor()` - set color of conatiner (only works when container is rendered as card)
+ `setColor()` - set color of container (only works when container is rendered as card)

### Inputs
Some inputs provide new features

+ `setIcon()` - add icon to input or button (Buttons, Links, Text inputs)
+ `setColor()` - add color to input or button (Buttons, Links, Checkbox, Lists)
+ `setTemplate()` - add custom latte template insted of basic render (All inputs)
+ `setTemplate()` - add custom latte template instead of basic render (All inputs)
+ `setPrepend()` - adds prepend part to [input group](https://getbootstrap.com/docs/5.0/forms/input-group/) (Text inputs, Select boxes)
+ `setAppend()` - adds append part to [input group](https://getbootstrap.com/docs/5.0/forms/input-group/) (Text inputs, Select boxes)
+ `setRenderInline()` - render label and input each in separate row, overwrites `renderInline` setting from Form (All non-button inputs)
+ `setFloatingLabel()` - input will be rendered with [floating labels](https://getbootstrap.com/docs/5.0/forms/floating-labels/) (Text inputs, Select box)
+ `setAutorenderSkip()` - skips rendering of input, eg. if input is rendered as part of another input with custom template (All inputs)
+ `setTooltip()` - add icon with tooltip to input (Text inputs, Checkbox, Lists, Selec boxes)
+ `setWrapClass()` - set class to outer div around label and input - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Selec boxes)
+ `setLabelWrapClass()` - set class to wrap div around label - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Selec boxes)
+ `setInputWrapClass()` - set class to wrap div around input - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Selec boxes)
+ `setTooltip()` - add icon with tooltip to input (Text inputs, Checkbox, Lists, Select boxes)
+ `setQuickCopy()` - add button to copy input value to clipboard (Text inputs, TextArea)
+ `setWrapClass()` - set class to outer div around label and input - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Select boxes)
+ `setLabelWrapClass()` - set class to wrap div around label - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Select boxes)
+ `setInputWrapClass()` - set class to wrap div around input - overwrites basic `col-` class (Text inputs, Checkbox, Lists, Select boxes)

### Duplicator example
```
Expand Down
31 changes: 27 additions & 4 deletions src/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
namespace ModulIS\Form;

use Nette\Application\UI\Form as UIForm;
use Nette\ComponentModel\IContainer;
use Nette\Forms\Controls\DateTimeControl;
use Nette\Forms\Controls\HiddenField;
use Nette\Utils\DateTime;
use Nette\Utils\Html;
use Stringable;
use function assert;

class Form extends UIForm
{
Expand All @@ -30,6 +33,8 @@ class Form extends UIForm

public bool $ajax = false;

private ?string $buttonClass = null;

public Html|string|null $title = null;

public ?string $icon = null;
Expand All @@ -49,7 +54,7 @@ class Form extends UIForm
private array $dividerArray = [];


public function __construct(?\Nette\ComponentModel\IContainer $parent = null, $name = null)
public function __construct(?IContainer $parent = null, $name = null)
{
parent::__construct($parent, $name);

Expand Down Expand Up @@ -79,7 +84,7 @@ public function renderForm()

foreach($groupArray as $groupTitle => $group)
{
\assert($group instanceof ControlGroup);
assert($group instanceof ControlGroup);
$inputs = null;

foreach($group->getInputArray() as $input)
Expand All @@ -95,7 +100,7 @@ public function renderForm()
/**
* Nette form hidden input
*/
$inputs .= $input instanceof \Nette\Forms\Controls\HiddenField ? $input->getControl() : $input->render();
$inputs .= $input instanceof HiddenField ? $input->getControl() : $input->render();

if(array_key_exists($input->getName(), $this->dividerArray))
{
Expand Down Expand Up @@ -213,7 +218,7 @@ public function getSubmitterArray(): array

foreach($this->getGroups() as $group)
{
\assert($group instanceof ControlGroup);
assert($group instanceof ControlGroup);
$submitterArray = array_merge($submitterArray, $group->getSubmitterArray());
}

Expand Down Expand Up @@ -515,6 +520,24 @@ public function setIcon(string $icon): self
}


/**
* Default class(es) for all form buttons (e.g. "rounded rounded-4").
* Priority: setClass() on the button overrides this.
*/
public function setButtonClass(string $class): self
{
$this->buttonClass = $class;

return $this;
}


public function getButtonClass(): ?string
{
return $this->buttonClass;
}


public function setNoValidate(bool $noValidate = true): self
{
$this->noValidate = $noValidate;
Expand Down
14 changes: 11 additions & 3 deletions src/control/Button.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace ModulIS\Form\Control;

use Kravcik\LatteFontAwesomeIcon\Extension;
use ModulIS\Form\Helper;
use Nette\Utils\Html;

Expand All @@ -13,6 +14,7 @@ class Button extends \Nette\Forms\Controls\Button implements Renderable
use Helper\Color;
use Helper\AutoRenderSkip;
use Helper\ControlClass;
use Helper\ButtonRounded;

public function getCoreControl(): Html|string
{
Expand All @@ -24,9 +26,15 @@ public function getCoreControl(): Html|string

$button = Html::el('button')
->name($this->getName())
->class('btn btn-' . $color . ($input->getAttribute('class') ? ' ' . $input->getAttribute('class') : ''))
->addHtml($this->icon ? \Kravcik\LatteFontAwesomeIcon\Extension::render($this->icon) : '')
->addHtml($label);
->type('button');

$button->appendAttribute('class', 'btn px-4')
->appendAttribute('class', 'btn-' . $color)
->appendAttribute('class', $this->getFormButtonClass())
->appendAttribute('class', (string) $input->getAttribute('class'));

$button->addHtml($this->icon ? Extension::render($this->icon) : '')
->addHtml($this->translate($label));

if($this->getOption('id'))
{
Expand Down
18 changes: 17 additions & 1 deletion src/control/DependentMultiSelect.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,25 @@ public function __construct($label = null, array $parents = [], ?callable $depen
}


public function loadHttpData(): void
{
parent::loadHttpData();

$parentsValues = [];

foreach($this->parents as $parent)
{
$parentsValues[$parent->getName()] = $parent->getValue();
}

$data = $this->getDependentData([$parentsValues]);
$this->setItems($data->getItems());
}


public function getValue(): array
{
return $this->getValue();
return parent::getValue();
}


Expand Down
48 changes: 29 additions & 19 deletions src/control/Duplicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@

namespace ModulIS\Form\Control;

use Closure;
use Latte\Engine;
use ModulIS\Form\Container;
use ModulIS\Form\DuplicatorContainer;
use ModulIS\Form\Helper\AutoRenderSkip;
use ModulIS\Form\Helper\Template;
use Nette;
use Nette\Application\UI\Presenter;
use Nette\Forms\Control;
use Nette\Forms\Form;
use Nette\Forms\SubmitterControl;
use Nette\Utils\Html;
use Nette\Utils\Strings;
use Traversable;
use function assert;

class Duplicator extends \ModulIS\Form\Container implements Renderable
class Duplicator extends Container implements Renderable
{
use \ModulIS\Form\Helper\AutoRenderSkip;
use \ModulIS\Form\Helper\Template;
use AutoRenderSkip;
use Template;

public bool $forceDefault = false;

Expand Down Expand Up @@ -48,7 +59,7 @@ public function __construct($factory, int $createDefault = 0, bool $forceDefault
$this->loadHttpData();
$this->createDefault();
});
$this->monitor(\Nette\Forms\Form::class);
$this->monitor(Form::class);

if(!self::$containerClass)
{
Expand All @@ -57,7 +68,7 @@ public function __construct($factory, int $createDefault = 0, bool $forceDefault

try
{
$this->factoryCallback = \Closure::fromCallable($factory);
$this->factoryCallback = Closure::fromCallable($factory);
}
catch(Nette\InvalidArgumentException $e)
{
Expand Down Expand Up @@ -96,7 +107,7 @@ public function render(): Html|string
{
if($this->templatePath)
{
return (new \Latte\Engine)->renderToString($this->templatePath, $this);
return (new Engine)->renderToString($this->templatePath, $this);
}

if($this->autoRenderSkip === true)
Expand Down Expand Up @@ -124,7 +135,7 @@ public function render(): Html|string

foreach($this->getComponents() as $key => $container)
{
\assert($container instanceof DuplicatorContainer || $container instanceof DuplicatorCreateSubmit);
assert($container instanceof DuplicatorContainer || $container instanceof DuplicatorCreateSubmit);
if($container instanceof DuplicatorCreateSubmit)
{
continue;
Expand All @@ -142,7 +153,7 @@ public function render(): Html|string

foreach($container->getComponents() as $duplicatorInput)
{
\assert($duplicatorInput instanceof Renderable);
assert($duplicatorInput instanceof Renderable);
if($duplicatorInput instanceof Button || $duplicatorInput instanceof DuplicatorRemoveSubmit || $duplicatorInput instanceof Link)
{
$buttons .= $duplicatorInput->render();
Expand Down Expand Up @@ -191,7 +202,7 @@ public function render(): Html|string
}

$card = Html::el('div')
->id('container' . \Nette\Utils\Strings::capitalize($this->getName()))
->id('container' . Strings::capitalize($this->getName()))
->class($duplicatorContainerClass)
->addHtml($header . $body . $footer);

Expand All @@ -203,19 +214,19 @@ public function render(): Html|string

public function setFactory($factory): void
{
$this->factoryCallback = \Closure::fromCallable($factory);
$this->factoryCallback = Closure::fromCallable($factory);
}


public function getContainers(?bool $recursive = false)
{
return $this->getComponents($recursive, \ModulIS\Form\Container::class);
return $this->getComponents($recursive, Container::class);
}


public function getButtons(?bool $recursive = false)
{
return $this->getComponents($recursive, Nette\Forms\SubmitterControl::class);
return $this->getComponents($recursive, SubmitterControl::class);
}


Expand All @@ -234,8 +245,7 @@ protected function createComponent($name): ?Nette\ComponentModel\IComponent

private function getFirstControlName()
{
$components = $this->getComponents(false, \Nette\Forms\Control::class);
$controls = is_array($components) ? $components : iterator_to_array($components);
$controls = $this->getComponents(false, Control::class);
$firstControl = reset($controls);
/* @phpstan-ignore-next-line */
return $firstControl ? $firstControl->name : null;
Expand Down Expand Up @@ -299,7 +309,7 @@ public function setValues(array|object $values, bool $erase = false, bool $onlyD
{
foreach($values as $name => $value)
{
if((is_array($value) || $value instanceof \Traversable) && !$this->getComponent(strval($name), false))
if((is_array($value) || $value instanceof Traversable) && !$this->getComponent(strval($name), false))
{
$this->createOne($name);
}
Expand All @@ -319,7 +329,7 @@ protected function loadHttpData()

foreach((array) $this->getHttpData() as $name => $value)
{
if((is_array($value) || $value instanceof \Traversable) && !$this->getComponent(strval($name), false))
if((is_array($value) || $value instanceof Traversable) && !$this->getComponent(strval($name), false))
{
$this->createOne($name);
}
Expand Down Expand Up @@ -355,7 +365,7 @@ private function getHttpData()
{
if($this->httpPost === null)
{
$path = explode(self::NameSeparator, $this->lookupPath(\Nette\Forms\Form::class));
$path = explode(self::NameSeparator, $this->lookupPath(Form::class));
$this->httpPost = Nette\Utils\Arrays::get($this->getForm()->getHttpData(), $path, null);
}

Expand Down Expand Up @@ -401,14 +411,14 @@ public function isAllFilled(array $exceptChildren = []): bool
{
$components = [];

foreach($this->getComponents(false, \Nette\Forms\Control::class) as $control)
foreach($this->getComponents(false, Control::class) as $control)
{
$components[] = $control->getName();
}

foreach($this->getContainers() as $container)
{
foreach($container->getComponents(true, \Nette\Forms\SubmitterControl::class) as $button)
foreach($container->getComponents(true, SubmitterControl::class) as $button)
{
$exceptChildren[] = $button->getName();
}
Expand Down
Loading
Loading