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

Using Blade Components in a Table #1489

Closed
tabuna opened this issue Jan 7, 2021 · 2 comments
Closed

Using Blade Components in a Table #1489

tabuna opened this issue Jan 7, 2021 · 2 comments
Assignees
Labels
Docs Must be added to documentation

Comments

@tabuna
Copy link
Member

tabuna commented Jan 7, 2021

Is your feature request related to a problem? Please describe.

I like to use components to display values in a table. This allows you to perform some operations, for example, dynamically changing the color/description/other depending on the state.

namespace App\View\Components;

use Illuminate\View\Component;
use App\Models\Order;

class OrderShortInformation extends Component
{
    /**
     * @var Order
     */
    public $order;

    /**
     * Create the component instance.
     *
     * @param  Order $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * @return bool
     */
    public function status()
    {
        $descriptions = [
            1 => __('In the process'),
            2 => __('Paid'),
            3 => __('Cancellation'),
            4 => __('Refund'),
        ];

        if (array_key_exists($this->order->status, $descriptions)) {
            return $descriptions[$this->order->status];
        }

        return 'Unknown';
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|\Closure|string
     */
    public function render()
    {
        return view('components.order.short-information');
    }
}

For example, there is an Order model, and depending on the status, we can show different descriptions in our components.
This is much nicer than specifying things directly in the view or creating special areas for such processing.

The problem is that Laravel does not provide by default the ability to render a component as a PHP class.

Describe the solution you'd like

I suggest adding straightforward processing to correctly handle (non-nested) components to display them in a table.
For example, recording via view:

// Before
TD::make('index')->render(function (Order $order) {
    // Lots of abstract or explicit code ... 
    return view(...);
});

And now this some of the things into the component:

use App\View\CompochangingOrderShortInformation;

TD::make('index')->component(OrderShortInformation::class);

This will automatically substitute the value that is in the loop (row) into our component.

Describe alternatives you've considered

Using a class clearly might not be very good to use from packages. Since it is assumed that the component has a name by which it can be called, for example:

<x-order-short-information :order="$order"/>

It may be strange that the class name is used instead. This was chosen because of the IDE's and editors' auto-hints - convenience only.

In theory, we could do support for both formats.

Additional context

I also thought about passing additional arguments, but because the required data and DI are in the constructor, this is problematic to implement in the package.

For example, if we go to get something in the constructor, we get an error:

public function __construct(Application $application, Order $order)
{
    $this->order = $order;
    // ...
}

We can only fix this problem by passing the name of the expected argument:

use App\View\CompochangingOrderShortInformation;

TD::make('index')->component(OrderShortInformation::class, 'order');

But we may also need to pass additional things to the constructor:

public function __construct(Application $application, Order $order, int $limit = 300)
{
    $this->order = $order;
    // ...
}

As you can see, it requires more and more arguments each time:

TD::make('index')->component(OrderShortInformation::class, 'order', [
    'limit' => 100
]);

I am not sure that it will do more good for everyone (not just me) than create confusion in DI and required arguments.
What do you think about that?

@tabuna tabuna self-assigned this Jan 7, 2021
@tabuna tabuna added the Polls label Jan 7, 2021
@pqr
Copy link
Contributor

pqr commented Jan 10, 2021

TD::make('index')->component(OrderShortInformation::class, 'order', [
    'limit' => 100
]);

Looks good to me!

@lemyskaman
Copy link
Member

lemyskaman commented Jan 11, 2021

Why dont we use a interface for OrderShortInformation constructor, in wich we make he contract to use the params needed

and pass an instantiated object of the contract to OrderShortInformation on component() TD method, that way it would be more elegant

i don't know for sure if it work this is just illustrative:

TD::make('index')->component(OrderShortInformation::class,rowElementsParamsFromInterfaceObjec);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docs Must be added to documentation
Development

No branches or pull requests

3 participants