Replies: 4 comments 9 replies
-
Do you have an example of the input and output you're looking to achieve? 🤔 |
Beta Was this translation helpful? Give feedback.
-
Let me try to picture you: Components Definitionapp/View/Components/Page.phpnamespace App\View\Components;
use Illuminate\View\Component;
class PageComponent extends Component
{
public $title;
public $description;
public function __construct($title = null, $description = null)
{
$this->title = $title;
$this->description = $description;
}
public function toJson()
{
return json_encode([
'title' => $this->title ? $this->title->toJson() : null,
'description' => $this->description ? $this->description->toJson() : null,
'children' => $this->getChildren(),
]);
}
protected function getChildren()
{
// Return any child components or other Blade content
// Here, you would need to iterate over any passed slots or content
}
public function render()
{
// Return view for normal rendering, but we also support JSON conversion
return view('components.page');
}
} app/View/Components/Text.phpnamespace App\View\Components;
use Illuminate\View\Component;
class TextComponent extends Component
{
public $content;
public $weight;
public function __construct($content, $weight = null)
{
$this->content = $content;
$this->weight = $weight;
}
public function toJson()
{
return json_encode([
'type' => 'text',
'content' => $this->content,
'weight' => $this->weight,
]);
}
public function render()
{
return view('components.text');
}
} resources/views/components/page.blade.php<!-- we don't need anything here actually --> resources/views/components/text.blade.php<!-- we don't need anything here actually --> Page definition (using the components)resources/views/my-page.blade.php<x-page>
<x-slot name="title">
<x-text content="FOO" />
</x-slot>
<x-slot name="description">
<x-text content="Bar" />
</x-slot>
@if(rand(1, 10) > 5)
<x-text content="Random Text" />
@endif
<x-text content="Child 1" />
<x-text content="Child 2" />
</x-page> Rendering:Route::get('/json-output', function () {
return view('my-page')->render(); // This will now return the JSON
}); Expected output{
"title": {
"type": "text",
"content": "Foo",
"weight": "w-400"
},
"description": {
"type": "text",
"content": "Bar",
"weight": null
},
"children": [
{
"type": "text",
"content": "Child 1",
"weight": null
},
{
"type": "text",
"content": "Child 2",
"weight": null
}
]
} I can give you more examples if needed, but basically i want to intercept the rendering process, and instead of parsing the html i just need access to the component class and call |
Beta Was this translation helpful? Give feedback.
-
Tried to return a json from |
Beta Was this translation helpful? Give feedback.
-
Migrated this to a discussion instead. What you're looking to do would be technically possible with this library and writing a custom compiler, but you'd be re-implementing some of the plumbing around passed attributes. Do you need anything from regular components apart from the syntax? In your example, you mention you don't need anything in the component's views: <!-- we don't need anything here actually --> but also mention "normal" rendering: public function render()
{
// Return view for normal rendering, but we also support JSON conversion
return view('components.page');
} One approach you could look into that doesn't involve implementing a custom compiler is to create your own component base class that that pushes attribute data to a stack and then use that as the data when returning the final JSON. That should remove the need for a recursive compiler, re-implementing logic, or keeping track of children, etc. |
Beta Was this translation helpful? Give feedback.
-
Context:
I'm working on a Laravel project where I need to use Blade views to declare components but instead of having the components output HTML, I want them to return JSON. The goal is to leverage Blade's templating engine to define component structures, while ultimately generating JSON output from these components, recursively handling nested components and passing their properties.
Problem:
Laravel's Blade system is primarily designed to compile templates into HTML, and its standard flow compiles Blade templates into PHP that renders HTML when processed. However, for my use case, I need to customize this process to return JSON output from my components.
Key Challenges:
Blade Compilation vs Rendering Phases:
CardComponent
,PageComponent
, etc.) happens during the rendering phase.Blade directives:
@auth
or@foreach
in my templates to control the visibility of components or loop through them.Recursively Handling Nested Components:
PageComponent
might contain multipleCardComponent
s, and eachCardComponent
might have its own nestedTextComponent
s.Attempted Solutions:
render()
method in each component class to return JSON. This approach seems more feasible, as Blade interacts with the component class during the rendering phase (after compilation), and I can override therender()
method to output JSON instead of HTML.Request for Help:
Beta Was this translation helpful? Give feedback.
All reactions