EFTEC / BladeOne

The standalone version Blade Template Engine without Laravel in a single php file and without dependencies
https://www.escuelainformatica.cl/
Other
783 stars 120 forks source link

@pushonce doesn't seem to work as Laravel's blade. #192

Open n1njatalon opened 4 months ago

n1njatalon commented 4 months ago

When using @pushonce for some styles in a component, it seems that it is duplicating the styles. Looking at the docs and code it seems that the @pushonce will only work if used in the same file multiple times. However Laravel's blade uses it per component used as specified in their docs:

The @once directive allows you to define a portion of the template that will only be evaluated once per rendering cycle. This may be useful for pushing a given piece of JavaScript into the page's header using stacks. For example, if you are rendering a given component within a loop, you may wish to only push the JavaScript to the header the first time the component is rendered.

Here is copy of my component:

<div class="{{$additionalclasses ?? ""}}">
    @if($slot)
        <div class="d-flex column-gap-4">
            <p class="flex-grow-2 fw-bold mt-1">{!! $slot !!}</p>
        </div>
    @endif
    <div class="btn-group {{$slot ? "me-5" : ""}}" role="group">
        <input type="radio" class="btn-check" name="{{$name}}"
               id="{{$name}}Yes" autocomplete="off" value="1">
        <label class="btn btn-primary border rounded-start fw-bold" for="{{$name}}Yes">Yes</label>

        <input type="radio" class="btn-check" name="{{$name}}"
               id="{{$name}}No" autocomplete="off" value="0">
        <label class="btn btn-primary border rounded-end fw-bold" for="{{$name}}No">No</label>
    </div>
</div>

@pushonce('styles')
    <style>
        .btn-group>label {
            min-width: 50px;
        }
    </style>
@endpushonce
MichelJonkman commented 1 month ago

I'm experiencing the same issue, this is normally a very useful feature so it'd be very nice to see this brought inline with the way Laravel works!

MichelJonkman commented 1 month ago

Changing the compilePushOnce() method to the below code will fix it:

public function compilePushOnce($expression): string
{
    $key = '';

    if ($this->currentView) {
        $key = '_' . $this->currentView;
    }

    $key = '__pushonce__' . \trim(\substr($expression, 2, -2)) . $key;
    return $this->phpTag . "if(!isset(\$GLOBALS['$key'])): \$GLOBALS['$key']=1;  \$this->startPush$expression; ?>";
}

If @jorgecc @jorgecc-business-account could change this I would really appreciate it! I'd make a pull request but that's a little much work with how small of a change this is.

jorgecc commented 1 month ago

I added another change to the code. Now it is possible to display a stack() before it is called(), i.e.

Now this code is valid:

@stack("example1")
@push("example1")
hello
@endpush

and this code is also valid

@push("example1")
hello
@endpush
@stack("example1")

Example:

MichelJonkman commented 1 month ago

I added another change to the code. Now it is possible to display a stack() before it is called(), i.e.

Now this code is valid:

@stack("example1")
@push("example1")
hello
@endpush

and this code is also valid

@push("example1")
hello
@endpush
@stack("example1")

Example:

Is the issue described now fixed as well? I don't see any changes in the code regarding @pushonce