- PHP >= 7.4
- Laravel Framework >= 8.
- Nova >= 2.0
- Imagick PHP extension or GD Library (for Intervention Image)
NOTE: These instructions are for Laravel >= 8. If you are using prior version, please see the previous version's docs.
composer require novius/laravel-nova-visual-composer
Next, configure Intervention Image package :
Intervention Image configuration instructions
Some options that you can override are available.
php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="config"
JS Configuration
Some options (like wysiwyg config) are configurable from JS config file.
You can override it with :
php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="js"
In your app/Console/Kernel.php file, you should register a daily job to purge any stale files :
protected function schedule(Schedule $schedule)
{
$schedule->command('nova-visual-composer:purge-tmp-files')
->daily();
}
By default tmp file is stale considered after 24h. You can override this value in configuration file with seconds_before_purge_tmp_files
key.
Step 1
Create a long text column on your model's table.
$table->longText('content')->nullable();
Configure your model by adding object
to the desired column.
use Illuminate\Database\Eloquent\Model;
class Foo extends Model {
protected $casts = [
'content' => 'object',
];
}
Step 2
Add the field to your Nova resource.
use App\Nova\Resource;
use Novius\NovaVisualComposer\NovaVisualComposer;
class FooResource extends Resource
{
public function fields(Request $request)
{
return [
// ..
NovaVisualComposer::make('Content')
->stacked(),
// ..
];
}
}
Step 3
Display in your blade template.
@foreach($item->content as $row)
{!! $row->template::renderFront($row->content) !!}
@endforeach
Step 1
You have to publish lang and view files.
php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="config"
php artisan vendor:publish --provider="Novius\NovaVisualComposer\NovaVisualComposerServiceProvider" --tag="views"
Step 2
Create your own Row Template and link it into configuration file.
Row Template Class
namespace App\Nova\Templates\Rows;
use Novius\NovaVisualComposer\Templates\RowTemplateAbstract;
use Novius\NovaVisualComposer\Traits\HasImageField;
use Novius\NovaVisualComposer\Traits\HasPrunableFiles;
class ImageText extends RowTemplateAbstract
{
use HasImageField;
use HasPrunableFiles;
public static $name = 'image-text';
protected static function imageFieldsIndexes(): array
{
return [0]; // Because image field is the first field that contains "js-visual-field" class of CRUD view
}
}
Add it to configuration file
return [
...
'templates' => [
\Novius\NovaVisualComposer\Templates\Article::class,
\Novius\NovaVisualComposer\Templates\ImageMultiple::class,
\Novius\NovaVisualComposer\Templates\ImageSimple::class,
\Novius\NovaVisualComposer\Templates\Separator::class,
\Novius\NovaVisualComposer\Templates\Title::class,
// Custom Template
\App\Nova\Templates\Rows\ImageText::class,
],
];
Step 3
Create template views (CRUD + front views).
resources/views/vendor/nova-visual-composer/templates/ImageText/crud.blade.php
TIPS :
- Each HTML field that you want to save must contains
js-visual-field
class. - If you want a wysiwyg add
js-wysiwyg
class to textarea field. - If you want an image upload field add
js-image-uploader
class to file field. - If you want a multiple images upload field add
js-image-uploader
class +multiple
attribute to file field.
<div class="shadow-md mb-4 w-full">
<div class="px-6 py-4">
<div class="font-bold text-xl mb-4">
{{ $templateDetails['name_trans'] }}
</div>
<div class="flex">
<div class="w-1/3 pr-3">
<div class="form-group">
<input type="file" class="filepond js-visual-field js-image-uploader">
</div>
</div>
<div class="w-2/3">
<div class="form-group mb-2">
<label class="block text-grey-darker text-sm font-bold mb-2">
{{ trans('nova-visual-composer::templates.'.$templateName.'.crud_pre_title') }}
</label>
<input class="js-visual-field w-full form-control form-input form-input-bordered"
type="text"/>
</div>
<div class="form-group mb-2">
<label class="block text-grey-darker text-sm font-bold mb-2">
{{ trans('nova-visual-composer::templates.'.$templateName.'.crud_title') }}
</label>
<input class="js-visual-field w-full form-control form-input form-input-bordered"
type="text"/>
</div>
<div class="form-group mb-2">
<label class="block text-grey-darker text-sm font-bold mb-2">
{{ trans('nova-visual-composer::templates.'.$templateName.'.crud_text') }}
</label>
<textarea name="content"
class="js-visual-field js-wysiwyg w-full form-control form-input-bordered py-2 h-20"></textarea>
</div>
</div>
</div>
</div>
</div>
resources/views/vendor/nova-visual-composer/templates/ImageText/front.blade.php
@php
if (empty($content) || !is_array($content)) {
return;
}
list(
$images,
$preTitle,
$title,
$htmlContent,
) = $content;
$image = is_array($images) ? array_shift($images) : null;
@endphp
<div class="block-image-text">
@if (!empty($image))
<img src="{{ asset('storage/'.$image) }}"/>
@endif
@if (!empty($preTitle))
<h5 class="pre-title">
{{ $preTitle }}
</h5>
@endif
@if (!empty($title))
<h3 class="title">
{{ $title }}
</h3>
@endif
@if (!empty($htmlContent))
<div class="content">
{!! $htmlContent !!}
</div>
@endif
</div>
Step 4
Add your translations to language files.
resources/lang/vendor/nova-visual-composer/fr/templates.php
return [
...
'image-text' => [
'name' => 'Image / texte',
'crud_pre_title' => 'Sur-titre',
'crud_title' => 'Titre',
'crud_text' => 'Texte',
],
];
Run php-cs with:
composer run-script lint
Contributions are welcome! Leave an issue on Github, or create a Pull Request.
This package is under GNU Affero General Public License v3 or (at your option) any later version.