Skip to content

Instantly share code, notes, and snippets.

@calebporzio
Last active October 21, 2022 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save calebporzio/7b75160d35d05b14b8d390214ddec3fd to your computer and use it in GitHub Desktop.
Save calebporzio/7b75160d35d05b14b8d390214ddec3fd to your computer and use it in GitHub Desktop.

Help me solve morphdom woes in Livewire

Blade "@if" statements can sometimes cause problems in Livewire.

I can eliminate those problems if I can inject markers around those conditional block like so:

@if (...)
    <div>foo</div>
@endif

Should render to something like:

<!-- IF -->
    <div>foo</div>
<!-- ENDIF -->

Problem is: @if can be used inside HTML elements, like so:

<div @if (...) class="hidden" @endif">

Which would render to:

<div <!-- IF --> class="hidden" <!-- ENDIF -->>

Which browsers are NOT cool with (can't have comments inside an HTML tag).

So I feel like there are two solution paths:

Path 1: A seperate directive

The simplest way to solve this problem would be to introduce a dedicated directive for injecting those markers. Something like `@wireIf":

@wireIf (...)
    <div>foo</div>
@endwireIf

Pros:

  • Simple & explicit

Cons:

  • You would have to rememeber two distinct directives and know when to use which
  • I can't think of any names or APIs that don't feel a little icky
    • @wireIf
    • @safeIf (Not in love with these names)
    • @if (..., true) (a second param feels very not ideal lol)
    • <wire:if :condition="..."> (using the element syntax makes "else" statements weird)
    • <wired-control :if="...">

Path 2: Something intelligent (but complex)

In a perfect world, I can hide all these concerns from developers entirely by intelligently injecting the markers only when not inside an HTML tag.

For example:

@if (...)
    <div>foo</div>
@endif

Would add the markers, but <div @if... would not.

No problem, can't I use some regex to determine at runtime if the contents of @if start with a new element?

Well yes, that's easy, BUT:

Because these markers need to be added when the condition is both true and false, I can't scrape the contents of @if at runtime (because false conditions dont render).

I would have to preprocess the Blade files themselves, regex for @if () ... @endif, determine if a marker shold be added or not and add them in the compiled template.

While this is possible, I'm wondering if the complexity of regexing @if statements is too much. Specically thinking of knowing when something like @if (foo()) ends (multiple closing parens).

Pros:

  • No added overhead for the user (invisible feature)

Cons:

  • Added invisible complexity. Will be very confusing if something goes wrong.
@riatabduramani
Copy link

Hi Caleb,

Regarding additional @if statements you want to introduce with livewire I see it as redundant, maybe as a suggestion, you go by specifying at the beginning of the code block as @wired and then the use @if statement.

Specifying @wired will look like annotation and it's something known for programmers.

@wired
@if (...)
    <div>foo</div>
@endif

Best regards,
Riat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment