Skip to content

Commit

Permalink
Various changes that should have been committed a long time ago
Browse files Browse the repository at this point in the history
  • Loading branch information
darrencoutts118 committed Aug 17, 2023
1 parent 46a274f commit 80babb4
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 19 deletions.
2 changes: 1 addition & 1 deletion config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'field' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full',
'form_error' => 'mb-4 font-bold text-white bg-red-800 p-3 rounded-md',
'group' => 'mb-4',
'label' => 'block font-medium text-sm text-gray-700',
'label' => 'block font-medium text-sm text-gray-700 dark:text-white',
'required' => 'text-red-800',
],
];
2 changes: 1 addition & 1 deletion resources/views/components/field-errors.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="{{ config('formulate.classes.field_error') }}">
<div class="{{ config('formulate.classes.field_error') }}" {{ $attributes }}>
@if (isset($errors))
{{ $errors->first($field->name) }}
@endif
Expand Down
12 changes: 12 additions & 0 deletions resources/views/components/field-group.blade.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
<div {!! $attributes !!}>
<x-dynamic-component component="{{ Formulate::getDynamicComponentName('label') }}" :field="$field" />

@if ($field->multiple)
<template x-for="(_, index) in form.{{ $field->name }}" :key='index'>
<div>
@endif

{{ $slot }}

<x-dynamic-component component="{{ Formulate::getDynamicComponentName('field-errors') }}" :field="$field" />

@if ($field->multiple)
</div>
</template>

<button type="button" @click="form.{{ $field->name }}.push('')" class="inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150">Add Another</button>
@endif
</div>
2 changes: 1 addition & 1 deletion resources/views/components/input.blade.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<x-dynamic-component component="{{ Formulate::getDynamicComponentName('field-group') }}" :field="$field">
<input type="{{ $type }}" name="{{ $name }}" id="{{ $id }}" value="{{ $value }}" {!! (($type == 'checkbox' || $type == 'radio') && $checked) ? 'checked="checked"' : '' !!} {!! ($required) ? 'required="required"' : '' !!} {!! $attributes !!} />
<input type="{{ $type }}" name="{{ $name }}{{ $multiple ? '[]' : '' }}" id="{{ $id }}" value="{{ is_string($value) ? $value: '' }}" {!! (($type == 'checkbox' || $type == 'radio') && $checked) ? 'checked="checked"' : '' !!} {!! ($required) ? 'required="required"' : '' !!} {!! $attributes !!} />
</x-dynamic-component>
12 changes: 12 additions & 0 deletions src/Components/BaseComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,16 @@ public function render()
return view($this->viewName(), Formulate::applyComponentMiddleware($this, $data))->render();
};
}

public function shouldRenderComponent()
{
return true;
}

public function shouldRender()
{
$componentName = class_basename($this);

return Formulate::applyMiddleware($this->shouldRenderComponent(), 'shouldRender' . $componentName);
}
}
8 changes: 4 additions & 4 deletions src/Components/FieldErrorComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Illuminate\Support\ViewErrorBag;
use Illuminate\View\Component;

class FieldErrorComponent extends Component
class FieldErrorComponent extends BaseComponent
{
public function __construct(public InputComponent $field)
{
Expand All @@ -17,17 +17,17 @@ public function __construct(public InputComponent $field)
*
* @return \Illuminate\View\View|\Closure|string
*/
public function render()
public function viewName()
{
return view('formulate::components.field-errors');
return 'formulate::components.field-errors';
}

/**
* Should this component render
*
* @return bool
*/
public function shouldRender()
public function shouldRenderComponent()
{
// get the errors that are being shared with the View
$errors = View::shared('errors', new ViewErrorBag());
Expand Down
21 changes: 18 additions & 3 deletions src/Components/FormComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@

class FormComponent extends Component
{
public ?Route $routeDetails = null;

public function __construct(
public string $action = '',
public ?string $method = null,
public ?string $route = null,
public array $rules = [],
?array $routeParams = null,
array | Model $data = []
) {
Expand All @@ -27,15 +30,27 @@ public function __construct(

if (!empty($route)) {
// get the route details
$routeDetails = new Route($route);
$this->routeDetails = new Route($route);

// we have a route, lets get the action from the url
$this->action = $routeDetails->createRouteUrlWithPossibleDefaultBindings($routeParams, $data);
$this->action = $this->routeDetails->createRouteUrlWithPossibleDefaultBindings($routeParams, $data);

// if we don't already have a method
if (empty($this->method)) {
// use the first available method
$this->method = $routeDetails->getDefaultHttpMethod();
$this->method = $this->routeDetails->getDefaultHttpMethod();
}

if (empty($rules)) {
$requestClassName = $this->routeDetails->getRequestClass();

if ($requestClassName) {
$requestClass = new $requestClassName;

if (method_exists($requestClass, 'rules')) {
$this->rules = $requestClass->rules();
}
}
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/Components/InputComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ public function __construct(
public string $type = 'text',
public mixed $value = null,
public bool $required = false,
public array $rules = [],
public bool $multiple = false
) {
// store an instance of this class as the field, this is passed to child components
$this->field = $this;

$this->form = Formulate::getForm();

// create instances of the necessary attribute bags
$this->groupAttributes = $this->newAttributeBag();
$this->labelAttributes = $this->newAttributeBag();
Expand Down Expand Up @@ -79,6 +83,14 @@ public function __construct(
// for all other fields, we just get the value from the service provider
$this->value = Formulate::getFieldValue($this->name, $value);
}

if (empty($this->rules) && !empty($this->form->rules) && array_key_exists($this->name, $this->form->rules)) {
$this->rules = $this->form->rules[$this->name];
}

if (!$this->required && in_array('required', $this->rules)) {
$this->required = true;
}
}

/**
Expand Down
15 changes: 11 additions & 4 deletions src/Formulate.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Formulate
* The current form
* @var FormComponent
*/
protected FormComponent $form;
protected ?FormComponent $form = null;

/**
* A collection of fields that are used within the current form
Expand Down Expand Up @@ -122,6 +122,11 @@ public function populateFormData(array | Model $data)
$this->formData = $data;
}

public function getForm()
{
return $this->form;
}

/**
* Return the current form data
*
Expand Down Expand Up @@ -157,9 +162,9 @@ public function getFields()
* Get the current field
*
*/
public function getCurrentField(): InputComponent
public function getCurrentField()
{
return $this->currentField;
return $this->fields->where('name', $this->currentField)->first();
}

/**
Expand Down Expand Up @@ -280,7 +285,9 @@ public function applyMiddleware($passable, $method)
$pipeline = new Pipeline(app());

// we don't need all of the middleware to have each method, so we need to filter
$filteredMiddleware = collect($this->middleware)->filter(function ($middleware) use ($method) {
$filteredMiddleware = collect($this->middleware)->filter(function ($middleware) {
return app($middleware)->shouldApply();
})->filter(function ($middleware) use ($method) {
return method_exists($middleware, $method);
})->toArray();

Expand Down
8 changes: 6 additions & 2 deletions src/FormulateComponentAttributeBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ class FormulateComponentAttributeBag extends ComponentAttributeBag
{
public function set($attribute, $value)
{
if (is_object($value)) {
$value = Js::from($value, JSON_FORCE_OBJECT);
if (is_object($value) || is_array($value)) {
if (!count($value)) {
$value = Js::from($value, JSON_FORCE_OBJECT);
} else {
$value = Js::from($value);
}
}

$this->attributes[$attribute] = $value;
Expand Down
2 changes: 2 additions & 0 deletions src/FormulateServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use AppKit\Formulate\Facades\Formulate as FormulateFacade;
use AppKit\Formulate\Middleware\ApplyAlpineJsFormAttributes;
use AppKit\Formulate\Middleware\ApplyFormThemeClassesMiddleware;
use AppKit\Formulate\Middleware\PrecognitionMiddleware;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

Expand Down Expand Up @@ -45,5 +46,6 @@ public function register()

FormulateFacade::registerMiddleware(ApplyFormThemeClassesMiddleware::class);
FormulateFacade::registerMiddleware(ApplyAlpineJsFormAttributes::class);
FormulateFacade::registerMiddleware(PrecognitionMiddleware::class);
}
}
22 changes: 22 additions & 0 deletions src/Helpers/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Routing\Route as RoutingRoute;
use Illuminate\Routing\Router;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Route as RouteFacade;
use ReflectionClass;

class Route
Expand All @@ -32,6 +33,13 @@ class Route
*/
protected Collection $params;

/**
* The middleware that are applied to the route
*
* @var array
*/
protected array $middleware = [];

public function __construct(public string $routeName)
{
// create a collection to store the params
Expand Down Expand Up @@ -66,6 +74,9 @@ public function __construct(public string $routeName)
$parameter->isOptional(),
));
}

// gather the middleware that are applied to this route
$this->middleware = RouteFacade::gatherRouteMiddleware($this->route);
}
}

Expand Down Expand Up @@ -143,4 +154,15 @@ public function getDefaultHttpMethod()
{
return app('router')->getRoutes()->getByName($this->routeName)->methods[0];
}

public function supportPrecognition()
{
$precognitionClass = 'Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests';

if (class_exists($precognitionClass) && in_array($precognitionClass, $this->middleware)) {
return true;
}

return false;
}
}
22 changes: 20 additions & 2 deletions src/Middleware/ApplyAlpineJsFormAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,41 @@
use AppKit\Formulate\Facades\Formulate;
use AppKit\Formulate\FormulateComponentAttributeBag;
use Closure;
use Illuminate\Support\Js;
use Illuminate\Support\Str;

class ApplyAlpineJsFormAttributes
class ApplyAlpineJsFormAttributes extends BaseMiddleware
{
public function getFormComponentAttributes(FormulateComponentAttributeBag $attributes, Closure $next)
{
// if the form is requesting x-data, but has nothing already set in the x-data attribute
if ($attributes->has('x-data') && $attributes->get('x-data') === true) {
// generate the x-data
$data = Formulate::getFields()->mapWithKeys(function ($field) {
if ($field->multiple) {
return [$field->name => $this->field->value ?? ['']];
}

return [$field->name => $field->value ?? ''];
});

// add in the x-data
$attributes->set('x-data', $data);
}

// pass onto the next middleware
return $next($attributes);
}

public function getInputComponentAttributes(FormulateComponentAttributeBag $attributes, Closure $next)
{
if ($this->form && $this->form->attributes->has('x-data') && !$attributes->has('x-model')) {
if ($this->field->multiple) {
$attributes->set('x-model', 'form.' . $this->field->name . '[index]');
} else {
$attributes->set('x-model', 'form.' . $this->field->name);
}
}

return $next($attributes);
}
}
2 changes: 1 addition & 1 deletion src/Middleware/ApplyFormThemeClassesMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use AppKit\Formulate\FormulateComponentAttributeBag;
use Closure;

class ApplyFormThemeClassesMiddleware
class ApplyFormThemeClassesMiddleware extends BaseMiddleware
{
public function getInputComponentAttributes(FormulateComponentAttributeBag $attributes, Closure $next)
{
Expand Down
24 changes: 24 additions & 0 deletions src/Middleware/BaseMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace AppKit\Formulate\Middleware;

use AppKit\Formulate\Facades\Formulate;
use AppKit\Formulate\FormulateComponentAttributeBag;
use Closure;

abstract class BaseMiddleware
{
public $form;
public $field;

public function __construct()
{
$this->form = Formulate::getForm();
$this->field = Formulate::getCurrentField();
}

public function shouldApply()
{
return true;
}
}
Loading

0 comments on commit 80babb4

Please sign in to comment.