How can I integrate Fancybox in Laravel Nova for an image gallery?

Updated: Feb 04, 2025

How can I integrate Fancybox in Laravel Nova for an image gallery?

To integrate Fancybox in Laravel Nova for an image gallery, you'll need to follow these steps:

  1. Install Fancybox: First, you need to install Fancybox in your Laravel Nova project. You can use a CDN or download it from the official website and place it in the public directory. For this example, we will use a CDN. Add the following CDN link to your app.scss file in the resources/assets/sass directory:
@import 'https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css';
  1. Install Fancybox JS: Add the following script tag to your app.js file in the resources/assets/js directory:
import $ from 'jquery';
import 'fancybox/src/jquery.fancybox.pack';

$(document).ready(function() {
    $('.fancybox').fancybox({
        buttons: ['zoom', 'share', 'save'],
        loop: true,
        thumbs: {
            autoStart: true
        }
    });
});
  1. Create a Fancybox resource: Create a new resource file for Fancybox in the resources/js directory called fancybox.js. This file will contain the configuration for Fancybox.
export default function () {
    return {
        init() {
            this.handleFancybox();
        },

        handleFancybox() {
            $('.fancybox').fancybox({
                buttons: ['zoom', 'share', 'save'],
                loop: true,
                thumbs: {
                    autoStart: true
                }
            });
        }
    }
}
  1. Register Fancybox: Register the Fancybox resource in the bootstrap.js file in the resources/js directory:
import Vue from 'vue';
import App from './App.vue';
import Fancybox from './fancybox';

Vue.use(Fancybox);

new Vue({
    render: h => h(App),
}).$mount('#app');
  1. Create a Fancybox field in Nova: Create a new field component for Fancybox in the resources/src/Field directory called Fancybox.php. This file will contain the configuration for the Fancybox field.
namespace App\Nova\Fields;

use Laravel\Nova\Fields\Field;

class Fancybox extends Field
{
    /**
     * The field's component.
     *
     * @var string
     */
    protected $view = 'nova-fields-fancybox::field';

    /**
     * The field's component properties.
     *
     * @var array
     */
    public $components = [
        'fancybox' => 'App\Nova\Fields\FancyboxResource'
    ];

    /**
     * Get the field's displayable name.
     *
     * @return string
     */
    public function name()
    {
        return 'Fancybox';
    }

    /**
     * Get the field's description.
     *
     * @return string
     */
    public function description()
    {
        return 'Display images in a Fancybox gallery.';
    }

    /**
     * Get the field's type.
     *
     * @return string
     */
    public function type()
    {
        return 'image-gallery';
    }

    /**
     * Get the field's settings.
     *
     * @return array
     */
    public function settings()
    {
        return [
            'imageSize' => [
                'type' => 'select',
                'name' => 'Image Size',
                'options' => [
                    'thumb' => 'Thumbnail',
                    'small' => 'Small',
                    'medium' => 'Medium',
                    'large' => 'Large',
                    'original' => 'Original'
                ],
                'default' => 'medium'
            ],
            'buttons' => [
                'type' => 'multiselect',
                'name' => 'Buttons',
                'options' => [
                    'zoom' => 'Zoom',
                    'share' => 'Share',
                    'save' => 'Save'
                ],
                'default' => ['zoom', 'share']
            ]
        ];
    }

    /**
     * Get the field's attributes.
     *
     * @return array
     */
    public function attributes()
    {
        return [
            'class' => 'fancybox'
        ];
    }

    /**
     * Get the field's CSS classes.
     *
     * @return array
     */
    public function classes()
    {
        return ['form-control'];
    }

    /**
     * Get the field's JavaScript.
     *
     * @return string
     */
    public function script()
    {
        return '//resources/js/fancybox.js';
    }
}
  1. Create a Fancybox resource: Create a new resource file for Fancybox in the resources/js directory called FancyboxResource.js. This file will contain the configuration for the Fancybox component.
import Vue from 'vue';
import Fancybox from 'fancybox/src/jquery.fancybox';

Vue.component('fancybox', {
    data() {
        return {
            options: {
                buttons: [],
                imageSize: 'medium'
            }
        };
    },

    props: {
        value: {
            type: Array,
            required: true
        },

        imageSize: {
            type: String,
            default: 'medium'
        },

        buttons: {
            type: Array,
            default: ['zoom']
        }
    },

    mounted() {
        this.options.buttons = this.buttons;
        this.$nextTick(() => {
            $(this.$el).fancybox({
                padding: 0,
                infobar: false,
                toolbar: false,
                imageScaleType: 'none',
                imageWidth: this.imageSize,
                imageHeight: this.imageSize,
                afterLoad: function(instance, slide) {
                    instance.image.width = instance.image.width * (100 / instance.image.width) * instance.image.height / 100;
                    instance.image.height = instance.image.height;
                }
            });
        });
    },

    template: `
        <div class="form-control" :class="{ 'has-value': value.length > 0 }" @click="open">
            <input type="hidden" name="images" :value="value">
            <img v-if="value.length > 0" :src="value[0]" :alt="value[0]" class="img-fluid">
            <span v-else class="placeholder text-muted">No image selected</span>
        </div>
    `
});
  1. Use the Fancybox field: Now you can use the Fancybox field in your resource file. Add the following code to your resources/src/Fields/Image.php file:
use App\Nova\Fields\Fancybox as FancyboxField;

class Image extends Field
{
    /**
     * The field's component.
     *
     * @var string
     */
    protected $view = 'nova-fields-image::field';

    /**
     * Create a new instance of the field.
     *
     * @param  string  $name
     * @param  string|callable $value
     * @param  array  $config
     * @return void
     */
    public function __construct($name, $value = null, array $config = [])
    {
        parent::__construct($name, $value, $config);

        $this->withMeta([
            'type' => 'image',
            'component' => FancyboxField::class
        ]);
    }
}
  1. Use