Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Expose the view component stack and keep full components on stack #36512

Closed
wants to merge 3 commits into from

Conversation

inxilpro
Copy link
Contributor

@inxilpro inxilpro commented Mar 8, 2021

This is an alternative approach to #36472. This PR includes two changes:

  1. It exposes View::getComponentStack() so that components can access the stack during render (for example, to find their parents)
  2. It allows for passing the full Blade Component to the startComponent() so that when components are accessed from the stack you have access to more than just their resolved view

It turns out that CompilesComponents::compileClassComponentOpening will need to be changed for this to work, since right now we're only passing $component->resolveView() rather than the whole component. But this approach does mean that there's not a need to track child components, and adds support for accessing components that are not directly next to each other on the stack (like my instant search example).

@taylorotwell
Copy link
Member

I really don't want to mess with component rendering too much and your use case is also already achievable:

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class InstantSearch extends Component
{
    public $types = [];

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct()
    {
        view()->share('instantSearchParent', $this);
    }

    /**
     * Add a type to the component.
     */
    public function addType($type)
    {
        $this->types[] = $type;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|string
     */
    public function render()
    {
        return function ($data) {
            return view(
                'components.instant-search',
                ['types' => $this->types] + $data
            )->render();
        };
    }
}

The parent:

<div id="instantsearch-container">
    {{ $slot }}
</div>

<script>
    @foreach ($types as $type)
        {{ $type }}
    @endforeach
</script>

In any child component of that parent:

@php $instantSearchParent->addType($type) @endphp

<div>
    Instant Search Child {{ $type }}
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants