0

I'm trying to reuse the same HTML code in both PHP and Javascript. In PHP I'm using Laravel's component mechanism to load the file passing the necessary parameters.

@foreach($files as $file)
    <x-my-file name="my_name[][image]" imageId="{{ $file->id }}" imageUrl="{{ $file->url }}" />
@endforeach

It's working just fine.

At the bottom of the page, I'm using jQuery like below:

@push('scripts')
    <script>
        var imageId = null;
        var imageUrl = '';
        jQuery(function($) {
            $('body').on('click', '#btn-add', function() {
                var imageId    = $(this).data('id');
                var imageUrl   = $(this).data('url');

                $('#target').append(`@include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => 15, 'imageUrl' => '/path/to/an-image.jpg'])`);
            });
        });
    </script>
@endpush

Everything just works fine. With every click, the same component is getting appended with the same data that I've passed.

But, if I replace the static values of the following line:

$('#target').append(`@include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => 15, 'imageUrl' => '/path/to/an-image.jpg'])`);

with the dynamic values I have, using the Javascript template literals:

$('#target').append(`@include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => ${imageId}, 'imageUrl' => ${imageUrl}])`);

The page stopped rendering with a Parse error from Laravel:

ErrorException
Use of undefined constant imageId - assumed 'imageId' (this will throw an Error in a future version of PHP)

Alternative?

I've seen some AJAX methods on loading blade in Javascript that I personally did not like.

Debugging

If I comment out the line, it still throws the same error until I remove the line completely. Hence I'm suspecting that the curly braces of the JS template literals (${}) are getting parsed as a Laravel blade syntax ({{}}).

Please note that instead of the backticks (`) I tried with the single quote and double quotes (as can be seen here), but getting errors as they are conflicting with the HTML code.

I've gone through the Laravel Documentation on Blade and JS Frameworks, but IMO, both the @ syntax and @verbatim are for the exact opposite purpose, and won't serve me.

Update

I eventually came up with an alternative to have blade in JavaScript:

@push('scripts')
    <script type="text/template" id="my-template">
        @include('components.my-file', ['name' => 'my_name[][image]'])
    </script>
    <script>
        var template = document.getElementById('my-template').innerHTML;
        console.log(template); // Successful grabbing the HTML.

        $(template).find('.image-placeholder').attr('src', imageUrl); // Replaced the HTML with the modified img tag only.
        console.log(template.prop('outerHTML'));
    </script>
@endpush

With this code, I can have the HTML perfectly without the dynamic data. The first console.log is showing the HTML perfectly:

<div>
    <img src="" alt="" class="image-placeholder">
    <input type="hidden" name="my_name[][image]" value="">
</div>

Now, the template is not a Laravel blade/component so far, so I have to put my dynamic data onto it. When I'm trying to put my dynamic data onto the HTML, the HTML is being replaced by the modified <img> string completely. The second console.log output is:

<img src="/dynamic-path/to/the-image.jpg" alt="" class="image-placeholder">
Mayeenul Islam
  • 4,532
  • 5
  • 49
  • 102

1 Answers1

0

Blade components are served by laravel.

After response returned from server blade component won't work anymore.

You can use some kind of placeholder and replace them dynamically as you did last time.

As example,

var template = document.getElementById('my-template').innerHTML;
template = template
  .replace('{src}', 'https://example.com/image.jpg')
  .replace('{id}', 'ImageID')
  .replace('{name}', 'my_name[][image]')

console.log(template)
<!-- 
<script type="text/template" id="my-template">
<x-my-file name="{name}" imageId="{id}" imageUrl="{src}" />
</script>
I am using a template below
-->
<script type="text/template" id="my-template">
<div>
    <img src="{src}" id="{id}" class="image-placeholder">
    <input type="hidden" name="{name}" value="">
</div>
</script>
  • Technically that is not possible. Because I'm calling a Blade Component, where I'm placing dyamic content by PHP. Suppose, the hidden field is like: ``, and the `img` tag is like: `@if($imageId && $upload) {{ resolveFieldName($upload) }} @endif`. I was well-versed about the template placeholder technique, but because of a Laravel component, I can't use this method. – Mayeenul Islam Jul 11 '21 at 09:34
  • You can use livewire – Hazzaz Bin Faiz Jul 11 '21 at 09:53