Closed Kimotu closed 4 months ago
Can you provide a sample code (controller) to reproduce the problem?
Sure. I'll provide an example on Monday.
@michalsn I found the problem. My method was defined with return type string (which usually works with html or json strings as output):
public function index() : string { ... }
When I change it to:
public function index() { ... }
it works.
Now I just have the problem that CI only seems to support Response Types for json and xml. So I would have to write a formatter for html. Or do you know an easy solution to return a html page with http type 201?
edit: I wrote a NullFormatter, that just returns the data
array unchanged and added 'text/html' in Config/Format.php
. Works for 201 (created), but leads to the next error when returning 400 for validation errors, since HTMX just handles 2XX codes. Maybe there is a reason not to support html in Response Traits and use them just for API calls that return json/xml anyway.
As for the response type, you can just set $this->stringAsHtml = true
, which should work fine - no need for writing a custom formatter.
If you want to handle error codes like 400 normally, you have to write some additional code:
document.addEventListener('htmx:responseError', function(event) {
let statusCode = event.detail.xhr.status;
let ignoredStatusCodes = [400];
if (ignoredStatusCodes.includes(statusCode)) {
event.preventDefault();
// Show content normally (you can customize this part)
// For example, replace the target element's content with the response text
event.detail.target.innerHTML = event.detail.xhr.responseText;
}
});
You can make it work only when specific elements trigger the request etc. https://htmx.org/events/#htmx:responseError The above code is not tested - and may require some changes.
Ok cool. I tried it in 4.5.0 and found $stringAsHtml = true
in upgrade guide, but response is still JSON. The HTMX part to ignore 400 works.
API\ResponseTrait and String Data
In previous versions, if you pass string data to a trait method, the framework returned an HTML response, even if the response format was determined to be JSON.
Now if you pass string data, it returns a JSON response correctly. See also Handling Response Types.
You can keep the behavior in previous (shouldn it be be current?) versions if you set the $stringAsHtml property to true in your controller.
I checked the source of ReponseTrait.php
$asHtml = $this->stringAsHtml ?? false;
// Returns as HTML.
if (
($mime === 'application/json' && $asHtml && is_string($data))
|| ($mime !== 'application/json' && is_string($data))
) {
// The content type should be text/... and not application/...
$contentType = $this->response->getHeaderLine('Content-Type');
$contentType = str_replace('application/json', 'text/html', $contentType);
$contentType = str_replace('application/', 'text/', $contentType);
$this->response->setContentType($contentType);
$this->format = 'html';
return $data;
}
But even, when I set $mime = application/json and $asHtml = true and verified that $data is of type string, it outputs json.
$this->stringAsHtml = true; // --> $asHtml = true
$this->setResponseFormat('application/json'); // --> $mine = 'application/json'
return $this->fail(gettype("Test")); // --> gettype returns string and 'Test' is string => all conditions met
returns
{
"status": 400,
"error": 400,
"messages": {
"error": "string"
}
}
Perhaps you are talking about this? https://forum.codeigniter.com/showthread.php?tid=90589
Hey, good hint. But actually it seems, the problem is RespondTrait itself. All failure-methods just return JSON.
return $this->respond(view('home'),400);
or $this->respondCreated(view('home'));
respect $this->stringAsHtml = true;
and return HTML.
return $this->fail(view('home'),400);
or $this->failValidationError(view('home'));
just return JSON.
Well, now that I know the stringAsHtml flag, I can use the response-methods and manually set the error codes.
Hint: I checked the source of RespondTrait and all methods finally call a generic respond()-method, but failure-methods first call a generic fail()-method that sets an error array as $data and then calls the generic respond()-method. I guess this error array forces the output to be JSON, because in format()-method the array does not match the is_string($data) check.
You can now use HTMLFormatter
- https://michalsn.github.io/codeigniter-htmx/html_formatter/
How do I return API-Responses? I use this htmx lib in a ResourcePresenter and want to return codes matching the action (201 => created, 202 => accepted, ...).
But when I include ResponseTrait and return
$this->respondCreated()
, I getAny hint/idea how to fix it?