Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The "responseError" variable in Snowboard is null when a ValidationException is thrown #1211

Open
diegoflorez opened this issue Sep 23, 2024 · 2 comments

Comments

@diegoflorez
Copy link

diegoflorez commented Sep 23, 2024

Winter CMS Build

1.2

PHP Version

8.1

Database engine

MySQL/MariaDB

Plugins installed

No response

Issue description

When submitting a form using Snowboard.request in WinterCMS, validation errors that should be caught in the responseError of the error handler are instead returned in the responseData of the error handler.

The expected behavior is that validation errors, when thrown as a ValidationException, should be returned in responseError. However, they are currently being returned in responseData, which is inconsistent with the expected Snowboard behavior for error handling.

Steps to replicate

  1. Create a simple form in WinterCMS and trigger a validation error using the ValidationException class.
  2. Use the following form partial and backend handler code to replicate the issue:

Form Partial (HTML + JS)

<form id="subscription-form" class="row mb-0">
    <!-- Name Input -->
    <div class="form-group">
        <label for="name">Name</label>
        <input type="text"
               name="name"
               id="name"
               class="required"
               placeholder="John Doe"
               required>
    </div>

    <!-- Email Input -->
    <div class="form-group">
        <label for="email">Email</label>
        <input type="email"
               name="email"
               id="email"
               class="required"
               placeholder="[email protected]"
               required>
    </div>

    <!-- Message Input -->
    <div class="form-group">
        <label for="message">Message</label>
        <textarea name="message"
                  id="message"
                  class="required"
                  cols="30"
                  rows="5"
                  placeholder="Please let us know how we can help you..."
                  required></textarea>
    </div>

    <!-- Submit Button -->
    <div class="col-12">
        <button type="submit">Subscribe</button>
    </div>
</form>

<div class="form-result"></div>

<script>
  document.addEventListener('DOMContentLoaded', function () {
  const form = document.getElementById('subscription-form');
  const formResult = document.querySelector('.form-result');

  form.addEventListener('submit', function (e) {
    e.preventDefault();

    // Trigger a Snowboard request
    Snowboard.request(form, 'onSubscribe', {
      loading: form.querySelector('button'),
      success: function (response) {
        // Handle success
        formResult.innerHTML = `<div class="alert alert-success">${response.message}</div>`;
        form.reset();
      },
      error: function (response, request) {
        // Expected: responseError contains the error details
        // Actual: validation errors are returned in request.responseData

        console.log('Error: ', request.responseError); // This is null
        console.log('Data: ', request.responseData); // This contains the validation errors

        // Display error messages
        if (request.responseData && request.responseData.X_WINTER_ERROR_FIELDS) {
          let errorMessage = '<div class="alert alert-danger"><ul>';
          Object.keys(request.responseData.X_WINTER_ERROR_FIELDS).forEach(function (field) {
            request.responseData.X_WINTER_ERROR_FIELDS[field].forEach(function (error) {
              errorMessage += `<li>${error}</li>`;
            });
          });
          errorMessage += '</ul></div>';
          formResult.innerHTML = errorMessage;
        } else {
          formResult.innerHTML = `<div class="alert alert-danger">${response.message}</div>`;
        }
      }
    });
  });
});
    
</script>

Backend Handler (PHP)

use Winter\Storm\Exception\ValidationException;

public function onSubscribe()
{
    $data = post();

    // Validation rules
    $rules = [
        'name' => 'required|string|max:255',
        'email' => 'required|email',
        'message' => 'required|string|max:500',
    ];

    // Validate input data
    $validator = Validator::make($data, $rules);

    if ($validator->fails()) {
        throw new ValidationException($validator); // Should return in responseError
    }

    // Simulate a successful save to the database
    return [
        'message' => 'Thank you for subscribing!',
    ];
}

Expected Behavior:

When a ValidationException is thrown, the error response should be captured in responseError in the error handler of the Snowboard.request.

Actual Behavior:

  • The validation errors are being returned in responseData instead of responseError.
  • responseError is null in the error function.

Possible Fix:

Ensure that validation errors, when thrown as ValidationException, are returned in the responseError instead of responseData.

Environment:

  • WinterCMS version: 1.2.x
  • Snowboard: Latest
  • PHP version: 8.1

Thank you for looking into this issue!

Workaround

No response

@diegoflorez diegoflorez added needs review Issues/PRs that require a review from a maintainer Type: Unconfirmed Bug labels Sep 23, 2024
@LukeTowers
Copy link
Member

@bennothommo any thoughts?

@bennothommo
Copy link
Member

@diegoflorez this is partially intended, based on the behavior of the previous AJAX framework.

Validation errors in the PHP side are returned with a response code of HTTP 406 Not Acceptable, which in the old framework was interpreted as a "successful" response, because it may include partial updates (such as displaying said validation errors in a specific way in a component, for example). Thus, the validation errors are simply returned as response data, and we have kept that behavior intact with Snowboard.

However, the responseError variable is reserved for the main exception message and should be passed through, but it appears it may not be. So that particular part of the functionality may have a bug.

@bennothommo bennothommo removed the needs review Issues/PRs that require a review from a maintainer label Oct 3, 2024
@bennothommo bennothommo changed the title Validation Errors in Ajax Requests are Returned in responseData instead of responseError The "responseError" variable in Snowboard is null when a ValidationException is thrown Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants