Skip to content

Instantly share code, notes, and snippets.

@Zakarialabib
Last active December 11, 2022 15:57
Show Gist options
  • Select an option

  • Save Zakarialabib/ef0caaf91aa5ca8860523dd171e52eb7 to your computer and use it in GitHub Desktop.

Select an option

Save Zakarialabib/ef0caaf91aa5ca8860523dd171e52eb7 to your computer and use it in GitHub Desktop.
LiveBuilder with Livewire Laravel
<div x-data="{ edit: {{ $edit ? 'true' : 'false' }} }">
<div>
<button
x-show="!edit"
@click="edit = true"
class="btn btn-primary"
>
Edit Sections
</button>
</div>
{{-- Use the `x-show` directive to toggle the visibility of the form based on the value of the `edit` variable. --}}
<form
x-show="edit"
wire:submit.prevent="updateSections"
x-cloak
>
{{-- Use the `x-model` directive to bind the form input values to the reactive properties in the component. --}}
@foreach ($sections as $index => $section)
<div class="form-group">
<label for="title-{{ $index }}">Title:</label>
<input
type="text"
id="title-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.title"
x-model="sections.{{ $index }}.title"
>
</div>
<div class="form-group">
<label for="description-{{ $index }}">Description:</label>
<textarea
id="description-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.description"
x-model="sections.{{ $index }}.description"
></textarea>
</div>
<div class="form-group">
<label for="image-{{ $index }}">Image:</label>
<input
type="file"
id="image-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.image"
x-model="sections.{{ $index }}.image"
>
</div>
@livewire('live-builder-styler', ['styles' => $section])
<button type="submit" class="btn btn-primary">Update Section</button>
@endforeach
<button type="button" @click="edit = false" class="btn btn-secondary">Cancel</button>
<button type="submit" class="btn btn-primary">Update Sections</button>
</form>
{{-- Use the `x-inner-html` directive to render the `LiveBuilder` component HTML in the view. --}}
<div x-data="{}" x-inner-html="{{ $liveBuilderHtml }}"></div>
</div>
<div>
<h2 class="text-xl font-bold mb-2">Styles</h2>
{{-- Use the `x-data` directive to define the `edit` variable, which is used to toggle the visibility of the form. --}}
<div x-data="{ edit: {{ $edit ? 'true' : 'false' }} }">
{{-- Use the `x-show` directive to toggle the visibility of the form based on the value of the `edit` variable. --}}
<form
x-show="edit"
wire:submit.prevent="updateStyles"
x-cloak
>
{{-- Use the `x-model` directive to bind the form input values to the reactive properties in the component. --}}
<div class="mb-4">
<label
for="title-size"
class="block text-gray-700 text-sm font-bold mb-2"
>
Title Size:
</label>
<input
type="number"
id="title-size"
class="form-control"
wire:model="styles.titleSize"
x-model="styles.titleSize"
>
</div>
<div class="mb-4">
<label
for="title-color"
class="block text-gray-700 text-sm font-bold mb-2"
>
Title Color:
</label>
<input
type="color"
id="title-color"
class="form-control"
wire:model="styles.titleColor"
x-model="styles.titleColor"
>
</div>
<div class="mb-4">
<label
for="title-align"
class="block text-gray-700 text-sm font-bold mb-2"
>
Title Alignment:
</label>
<select
id="title-align"
class="form-control"
wire:model="styles.titleAlign"
x-model="styles.titleAlign"
>
<option value="left">Left</option>
<option value="center">Center</option>
<option value="right">Right</option>
</select>
</div>
{{-- Other style options... --}}
<button type="submit" class="btn btn-primary">Update Styles</button>
</form>
{{-- Use the `x-show` directive to toggle the visibility of the style preview based on the value of the `edit` variable. --}}
<div x-show="!edit">
<h3
class="font-bold" x-bind:style="{
fontSize: styles.titleSize + 'px',
color: styles.titleColor,
textAlign: styles.titleAlign,
// Other styles...
}"
>
Preview Title
</h3>
{{-- Other style previews... --}}
<button
type="button"
@click="edit = true"
class="btn btn-primary"
>
Edit Styles
</button>
</div>
</div>
</div>
<div>
<h2 class="text-xl font-bold mb-2">Sections</h2>
@foreach ($sections as $index => $section)
{{-- Use the `x-data` directive to define the `edit` variable, which is used to toggle the visibility of the form. --}}
<div
class="section"
wire:key="{{ $index }}"
x-data="{ edit: {{ $edit ? 'true' : 'false' }} }"
>
{{-- Use the `x-show` directive to toggle the visibility of the form based on the value of the `edit` variable. --}}
<form
x-show="edit"
wire:submit.prevent="updateSection({{ $index }})"
x-cloak
>
{{-- Use the `x-model` directive to bind the form input values to the reactive properties in the component. --}}
<div class="mb-4">
<label
for="title-{{ $index }}"
class="block text-gray-700 text-sm font-bold mb-2"
>
Title:
</label>
<input
type="text"
id="title-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.title"
x-model="sections.{{ $index }}.title"
>
</div>
<div class="mb-4">
<label
for="description-{{ $index }}"
class="block text-gray-700 text-sm font-bold mb-2"
>
Description:
</label>
<textarea
id="description-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.description"
x-model="sections.{{ $index }}.description"
></textarea>
</div>
<div class="mb-4">
<label
for="image-{{ $index }}"
class="block text-gray-700 text-sm font-bold mb-2"
>
Image:
</label>
<input
type="file"
id="image-{{ $index }}"
class="form-control"
wire:model="sections.{{ $index }}.image"
x-model="sections.{{ $index }}.image"
>
</div>
@livewire('live-builder-styler', ['styles' => $section])
<button type="submit" class="btn btn-primary">Update Section</button>
</form>
{{-- Use the `x-show` directive to toggle the visibility of the section content based on the value of the `edit` variable. --}}
<div x-show="!edit">
<h3
class="text-2xl font-bold mb-2"
x-text="sections.{{ $index }}.title"
></h3>
<p
class="text-gray-700 text-base"
x-text="sections.{{ $index }}.description"
></p>
<img
x-bind:src="sections.{{ $index }}.image"
class="w-full"
x-show="sections.{{ $index }}.image"
>
<button
type="button"
@click="edit = true"
class="btn btn-primary"
>
Edit Section
</button>
</div>
</div>
@endforeach
</div>

This is an experimantation with CHATGPT

the idea is to make a livebuilder with livewire

<?php
namespace App\Http\Livewire;
use Livewire\Component;
class LiveBuilder extends Component
{
// Reactive properties to store the page title, description, and image.
public $title;
public $description;
public $image;
// Reactive property to store the sections for the page.
public $sections = [];
// Reactive property to track whether the user is currently editing a section.
public $edit = false;
// Use the `mount` lifecycle hook to initialize the reactive properties with any existing page data.
public function mount($page)
{
$this->title = $page->title;
$this->description = $page->description;
$this->image = $page->image;
$this->sections = $page->sections;
}
// Use the `save` method to handle the form submission and save the page to the database.
public function save()
{
// Validate the form input.
$this->validate([
'title' => 'required',
'description' => 'required',
'image' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
// Save the page to the database.
Page::create([
'title' => $this->title,
'description' => $this->description,
'image' => $this->image,
'sections' => $this->sections,
]);
// Redirect the user to the page they just created.
return redirect()->to(route('page', ['id' => $page->id]));
}
// Use the `addSection` method to add a new section to the page.
public function addSection()
{
$this->sections[] = [
'title' => '',
'description' => '',
'image' => '',
];
}
// Use the `updateSection` method to update an existing section on the page.
public function updateSection($index)
{
// Validate the form input.
$this->validate([
"sections.{$index}.title" => 'required',
"sections.{$index}.description" => 'required',
"sections.{$index}.image" => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
// Set the edit property to false to exit edit mode.
$this->edit = false;
}
// Use the `removeSection` method to remove a section from the page.
public function removeSection($index)
{
unset($this->sections[$index]);
}
}
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class LiveBuilderGenerator extends Component
{
// Reactive properties to store the sections and styles.
public $sections = [
[
'title' => 'Section 1',
'description' => 'This is the first section.',
'image' => '',
'titleSize' => '1.5rem',
'titleColor' => '#333',
'titleAlign' => 'left',
'descriptionSize' => '1rem',
'descriptionColor' => '#666',
'descriptionAlign' => 'left',
'position' => 'left'
]
];
public $edit;
// Use the `updated` lifecycle hook to generate the LiveBuilder component HTML when the sections or styles change.
public function updated($field)
{
if ($field === 'sections' || $field === 'styles') {
$this->generateLiveBuilder();
}
}
// Generate the LiveBuilder component HTML and store it in a reactive property.
public function generateLiveBuilder()
{
$this->liveBuilderHtml = view('livewire.livebuilder')
->with('sections', $this->sections)
->with('edit', $this->edit)
->render();
}
public function render()
{
return view('livewire.livebuilder-generator');
}
}
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class LiveBuilderStyler extends Component
{
// Reactive properties to store the title and description styles.
public $titleSize;
public $titleColor;
public $titleAlign;
public $descriptionSize;
public $descriptionColor;
public $descriptionAlign;
public $position;
// Use the `mount` lifecycle hook to initialize the reactive properties with any existing style data.
public function mount($styles)
{
$this->titleSize = $styles['titleSize'];
$this->titleColor = $styles['titleColor'];
$this->titleAlign = $styles['titleAlign'];
$this->descriptionSize = $styles['descriptionSize'];
$this->descriptionColor = $styles['descriptionColor'];
$this->descriptionAlign = $styles['descriptionAlign'];
$this->position = $styles['position'];
}
public function render()
{
return view('livewire.livebuilder-styler');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment