Comments (9)
Just tagged version 0.4.0
which loosens the return type declarations of the ResponseRenderer
interface. Feel free to reopen this issue if there are still problems left.
from arcanist.
There's a renderer available for Inertia.js. Have a look at this URL: https://github.com/laravel-arcanist/inertia-response-renderer
As for the blade templates, that comes out of the box. Please have a look at this demo video done before the package was released to grasp the core concepts and see how to implement a basic wizard. https://www.youtube.com/watch?v=R_9jNFYPqrE&t=5404s
If I have a JavaScript frontend project (Vue, React, Svelte, etc.)
I am only familiar with Vue.js. Vue.js allows you access to the Vuex store and since there are no full page reloads, I am guessing you could have your Vuex store handle that bit of saving the state between steps for you. Removing the need for Arcanist. Ideally, the wizard only enables you to collect data then it commits it at the end which is where you would make the API request.
from arcanist.
I think writing a RestApiResponseRenderer
would be pretty straight forward, since all you’d have to do is to return the wizard’s data as a JsonResponse
instead of a Blade or Inertia view.
So something like this
public function renderStep(WizardStep $step, AbstractWizard $wizard, $data)
{
return new JsonResponse($data);
}
I think the bigger problem for your use-case is the fact that you have a separate SPA for your frontend. Since you're now doing client-side routing, this might conflict with Arcanist since it will try and redirect you between the different steps of a wizard. I haven’t tried it out yet, but it’s possible that a library like axios would automatically take care of the redirection if the backend returns a redirect response.
from arcanist.
@ksassnowski your idea with the JsonResponse
is not working because the renderStep
have conflicting return types.
JsonResponse
and Response
have different trees.
We have a working MVP but we had to change return types in AbstractWizard
and Contracts\Renderer
.
Are you open for PR to fix the return types?
After the small changes we can provide a package with a renderer to use with a vue spa
.
Our change can be viewed in suenert@52ef0e0
We are open to discuss the right return types because forcing RedirectResponse
is an architectural thing.
from arcanist.
Can you elaborate a little bit on what exactly the issue with the JsonResponse
is? Because just from looking at your change, I don't quite understand what you were trying to do that conflicted with this return type.
I'm definitely open to make a change to the return types if it helps. I just want to understand the problem properly first.
from arcanist.
As you mentioned above to write a JsonRenderer
is straightforward and enough to build a Protocol
on top of archaist to drive an SPA.
The idea is in a vue
context:
Use the Vue Router for client side rounting an reimplement the two get routes of arcanist.
Build an JsonRenderer
to receive the data as json in the frontend.
To handle redirects build a Protocol on top of arcanist.
Example for a JsonRenderer
class JsonRenderer implements ResponseRenderer
{
public function renderStep(WizardStep $step, AbstractWizard $wizard, array $data = []): Response | Responsable | Renderable
{
$viewData = [
'arcanist' => array_filter([
'wizard' => $wizard->summary(),
'step' => $data,
])
];
return new JsonResponse($viewData);
}
public function redirect(WizardStep $step, AbstractWizard $wizard): RedirectResponse
{
return new JsonResponse([
'redirect' => [
'name' => 'step',
'params' => [
'wizardSlug' => $wizard::$slug,
'wizardId' => $wizard->getId(),
'step' => $step->slug,
]
]
]);
}
public function redirectWithError(WizardStep $step, AbstractWizard $wizard, ?string $error = null): RedirectResponse
{
return new JsonResponse([
'url' => route(
'wizard.' . $wizard::$slug . '.show',
[$wizard->getId(), $step->slug]
),
'error' => $error
]);
}
}
The Problem
This Renderer isn't working because it throws type mismatches for each function.
For renderStep
the JsonResponse
isn't a Response
.
For redirect
and redirectWithError
the JsonResponse
isn't a RedirectResponse
and can't be in anyway.
Solution
Add JsonResponse
or dive deeper into the inheritance tree an find a Class which both Responses rely on Symfony\Component\HttpFoundation\Response
.
To solve the problem with the RedirectResponse isn't so easy because that is a strong architectural decision to force a redirect. (That is forced in the AbstractWizard
as well).
The easy way is to add JsonReponse
to the types but that feels a bit against your vision.
Maybe we have to rethink how the Renderer
works with the Wizard to reduce the mismatches into one place and find good solution.
Quick idea come up while I am writing: Return Renderable Objects from the Renderer, so we have to overwrite 3 Renderable Objects instead of the Renderer. But don't know if that works with Redirects
.
Extended Problem
We want to build a form builder with vue on top of arcanist, that the ui is driven by the step fields definition. (Hello nova my old friend).
That works without any modification, our solution here is to use the Step::viewData
function, e.g:
/**
* Returns the view data for the template.
*/
public function viewData(Request $request): array
{
return [
'data' => $this->withFormData(),
'fields' => $this->fields(),
];
}
But we need additional infos for the Field
like $component = 'TextField
.
For that a change is needed:
You have build a make
function which uses new self
that is a problem when we want to extend the class.
Lines 17 to 20 in 14bd127
Here we need to use
new static
because we want an instance of the class we call the make
function on.
Hopefully that describes the problem in a better and more in depth way.
I am open to chat/voice etc. if you want.
I am planning to build two big application on this package because it is well thought out.
from arcanist.
Thanks for the thorough explanation. I think I got confused because your linked commit shows a diff with a previous commit from your fork where you had already added the JsonResponse
. I'm fine with changing the return types to allow for kinds of responses. I want to have a look how this can be simplified so it doesn't end up with a monstrous union type.
Regarding the Field
class, I'd be happy for a PR that changes self
to static
, both inside the function as well as the return type. This is a fairly straight-forward change that I could merge quickly.
The other changes require a bit more care since this also affects the existing renderers. I will have to tag new releases for all of them.
from arcanist.
The other changes require a bit more care since this also affects the existing renderers. I will have to tag new releases for all of them.
Let me know if we can assist you to make the change happen and/or discuss other solutions.
from arcanist.
We have one thing left:
To render fields in the frontend SPA we need to access the field list from the Render like this:
public function renderStep(WizardStep $step, AbstractWizard $wizard, array $data = [] ): Response | Responsable | Renderable
{
return new JsonResponse([
'wizard' => $wizard->summary(),
'step' => $step,
'fields' => $step->getFields(),
'formData' => $data,
]);
}
As you see we call a custom function getFields()
. We only need this because the fields()
function is protected.
Is there any chance to change that to public
?
https://github.com/laravel-arcanist/arcanist/blob/ecb3f51c5b63222f1c40d700218f09699f5b6f14/src/WizardStep.php#L91-94
from arcanist.
Related Issues (20)
- Inertia support HOT 7
- REST API Renderer HOT 1
- [REST API Renderer] Wizard Cancel force redirect Response HOT 3
- Overriding registerRoutes (for multilingual support, etc.) HOT 2
- Question about security HOT 7
- How should 404 errors be handled HOT 1
- Use the var that passed from action [question]
- A prepareForValidation method HOT 1
- Repeat option HOT 1
- laravel-arcanist/inertia-response-renderer 0.5.0 requires inertiajs/inertia-laravel ^0.4.1 -> found inertiajs/inertia-laravel[v0.4.1, ..., v0.4.5] but it conflicts with your root composer.json require (^0.5.1).
- Access level to fields() must be public HOT 1
- How to upload files? HOT 5
- Is version 1.0 accessible?
- Optional steps HOT 1
- How to validate an array of objects in wizard step HOT 1
- UnknownStepException
- Testing HOT 6
- arc lint doesnt see all the paths in the directory HOT 2
- Can we also contribute to the documentation somewhere? HOT 1
- Laravel Arcanist fail silently
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from arcanist.