Log1x / acf-composer

Compose ACF Fields, Blocks, Widgets, and Option Pages with ACF Builder on Sage 10.
https://github.com/Log1x/acf-composer
MIT License
423 stars 57 forks source link

Returning ACF field data for use with Javascript #88

Closed davidyv closed 3 years ago

davidyv commented 3 years ago

First of all, thanks so much for all your hard work with these packages for Sage 10.

I am trying to make some ACF fields data available to Javascript.

I have wp_add_inline_script() set up in enqueue() function in Chart.php( the block ), but It returns:

<script id='sage/app.js-js-before'>
csvURL = null; 
</script>

Steps to reproduce

$ wp acorn acf:block Chart

./app/Blocks/Chart.php

<?php

namespace App\Blocks;

use Log1x\AcfComposer\Block;
use StoutLogic\AcfBuilder\FieldsBuilder;

class Chart extends Block
{
    /**
     * The block name.
     *
     * @var string
     */
    public $name = 'Chart';

    /**
     * The block description.
     *
     * @var string
     */
    public $description = 'A simple Chart block.';

    /**
     * The block category.
     *
     * @var string
     */
    public $category = 'formatting';

    /**
     * The block icon.
     *
     * @var string|array
     */
    public $icon = 'editor-ul';

    /**
     * The block keywords.
     *
     * @var array
     */
    public $keywords = [];

    /**
     * The block post type allow list.
     *
     * @var array
     */
    public $post_types = ['post'];

    /**
     * The parent block type allow list.
     *
     * @var array
     */
    public $parent = [];

    /**
     * The default block mode.
     * preview
     * @var string
     */
    public $mode = 'edit';

    /**
     * The default block alignment.
     *
     * @var string
     */
    public $align = 'wide';

    /**
     * The default block text alignment.
     *
     * @var string
     */
    public $align_text = '';

    /**
     * The default block content alignment.
     *
     * @var string
     */
    public $align_content = '';

    /**
     * The supported block features.
     *
     * @var array
     */
    public $supports = [
        'align' => true,
        'align_text' => false,
        'align_content' => false,
        'anchor' => false,
        'mode' => false,
        'multiple' => true,
        'jsx' => true,
    ];

    /**
     * The block styles.
     *
     * @var array
     */
    public $styles = [
        [
            'name' => 'light',
            'label' => 'Light',
            'isDefault' => true,
        ],
        [
            'name' => 'dark',
            'label' => 'Dark',
        ]
    ];

    /**
     * The block preview chart data.
     *
     * @var array
     */
    public $example = [
        'items' => [
            ['item' => 'Item one'],
            ['item' => 'Item two'],
            ['item' => 'Item three'],
        ],
    ];

    /**
     * Data to be passed to the block before rendering.
     *
     * @return array
     */
    public function with()
    {
        return [
            'csv' => $this->csv(),
        ];
    }

    /**
     * The block field group.
     *
     * @return array
     */
    public function fields()
    {
        $chart = new FieldsBuilder('chart');

        $chart
            ->addFile('csv', [
                'return_format' => 'url',
                'min_size' => '1 KB',
                'max_size' => '5',
                'mime_types' => 'csv'
            ]);

        return $chart->build();
    }

    /**
     * Return the items field.
     *
     * @return array
     */
    public function csv()
    {
        return get_field('csv');
    }

    /**
     * Assets to be enqueued when rendering the block.
     *
     * @return void
     */
    public function enqueue()
    {
        $script  = 'csvURL = '. json_encode($this->csv()) .'; ';
        wp_add_inline_script('sage/app.js', $script, 'before');
    }

Any help on this would be much appreciated.

ghost commented 3 years ago

Hello! Does your csv() function return results when rendered within a blade template?

davidyv commented 3 years ago

Hello! Does your csv() function return results when rendered within a blade template?

Yes, it can return the correct result.

ghost commented 3 years ago

I may be wrong, but I don't think that what you're trying to do is currently supported.

Look at the data that is passed to enqueue during the block registration.

https://github.com/Log1x/acf-composer/blob/1dd67e5b40dc1d7207755b8b4442eacda2655029/src/Block.php#L246-L251

Unlike $this->render, the block object (and therefore your csv field) is not passed to the function.

If you wanted to get access to the block data, you'll have to fork this repo and change the code for this function's definition. Or, submit a PR and see if @Log1x wants to have that feature implemented.

davidyv commented 3 years ago

How to change the code to achieve this?

Thanks. I’m new to PHP, please forgive my ignorance.

ghost commented 3 years ago

You need to pass enqueue the variable that has the fields data. It's not exactly clear to me what that is, though, so I will not be the right person to help you with this.

But, basically, it you would change this: https://github.com/Log1x/acf-composer/blob/1dd67e5b40dc1d7207755b8b4442eacda2655029/src/Block.php#L246-L248 To this:

 'enqueue_assets' => function ($block) { 
     return $this->enqueue($block); 
 },

You'll also have to change the member definition here: https://github.com/Log1x/acf-composer/blob/1dd67e5b40dc1d7207755b8b4442eacda2655029/src/Block.php#L175-L183

To something like this:

    /**
     * Assets enqueued when rendering the block.
     *
     * @return void
     */
    public function enqueue($block)
    {
        //
    }

Now, inside of your own Chart class, match the same member definition for enqueue

 /**
     * Assets to be enqueued when rendering the block.
     *
     * @return void
     */
    public function enqueue($block)
    {
        var_dump($block); /* Take a look inside this variable and see if csv is there */
        $script  = 'csvURL = '. json_encode($this->csv()) .'; ';
        wp_add_inline_script('sage/app.js', $script, 'before');
    }

This isn't the right solution, but it's the basic idea. To make this solution correct, you need to pass the correct variable (i.e.: the variable with the csv field) to your enqueue function. I have no idea what that variable is, but from what I can tell it isn't block.

Log1x commented 3 years ago

I don't think the default enqueue_assets supports inline scripts (it's handled by ACF). You might have to use parse_blocks() or the like.

davidyv commented 3 years ago

Thank you very much!

I will compare it with the HTMLElement.dataset method to see who is more efficient.