mauricius / laravel-htmx

Laravel helper library for Htmx
MIT License
308 stars 14 forks source link

Request Validation Support #10

Open turculaurentiu91 opened 1 year ago

turculaurentiu91 commented 1 year ago

Hello, I was wondering if you plan on overriding or providing any kind of support for default Laravel request validation, ether direct or via FormRequests so we can respond with a view with validation errors rather than redirecting.

graemetait commented 1 year ago

I'd been playing around with achieving this before seeing this issue. Only real problem I had was that I can't get the FormRequest to extend the HtmxRequest class, as FormRequest is hardcoded to extend Laravel's Request class. This isn't an absolute requirement, but you then lose out on those extra functions that are very handy.

I was thinking that, given the simplicity of the additional methods in HtmxRequest, they could potentially be moved into a trait so they can be mixed in to the FormRequest.

mauricius commented 12 months ago

I'm not sure how helpful would be to override the default Laravel validation handling, given that from the request you don't get any indication of the view that has generated the error. The package cannot make any assumptions of how you're going to handle failed validation, because the approach may vary from application to application.

Nevertheless I tried to play with it this morning and I think a good pattern may be the following (to give you some context, this is taken from a basic Todo App, when an empty todo is submitted):

public function failedValidation(Validator $validator): void
{
  $request = app()->make(HtmxRequest::class);

  // or use $this->headers->get('HX-Request', 'false') if you don't want to use HtmxRequest
  if ($request->isHtmxRequest()) {
    // render just the form fragment with errors
    $view = View::renderFragment('todomvc.template', 'form', [
      'errors' => $validator->errors()
    ]);

    $response = with(new HtmxResponse())
      ->addRenderedFragment($view)
      ->reswap('innerHTML')
      ->retarget('form');

    throw new ValidationException($validator, $response);
  }

  parent::failedValidation($validator);
}
graemetait commented 12 months ago

@mauricius thanks for giving it a try! This is very similar to what I ended up with, and I agree that it therefore doesn’t make much sense to build in to your library as a pattern.

Also given how much code you may end up with to render the fragment correctly I think I’d personally rather just validate in the controller than in a FormRequest.