以编程方式渲染 Laravel 7 组件

Dan*_*Dan 8 laravel laravel-blade laravel-7

我有一个 Laravel 7 组件,如下所示

class Input extends Component
{
    public $name;
    public $title;
    public $value;
    public $type = 'text';

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct($name, $title)
    {
        $this->name = $name;
        $this->title = $title;
        $this->value = \Form::getValueAttribute($name);
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.fields.input');
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以像这样在 Blade 组件中渲染该字段:

<x-input name="name" :title="__('My field')" />

我需要在代码中创建和渲染该字段,我尝试了以下操作:

$field = new Input('name', 'My field');
$field->render();
Run Code Online (Sandbox Code Playgroud)

这会返回一个错误:

Undefined variable: title

我可以看到渲染函数被调用,但公共属性不可用于视图。我将如何呈现具有公共属性的组件?

小智 10

试试这个,它在 laravel 8 中对我有用,并且我检查了datalaravel 7 中是否存在该函数

$field = new Input('name', 'My field');
$field->render()->with($field->data());
Run Code Online (Sandbox Code Playgroud)

** 数据功能包括Component的方法、属性和属性。


cba*_*ier 7

Laravel 的最新版本(v.8.80) 应该可以帮助你实现你想要通过pull 做的事情 #40425

Blade::render('<x-input name="name" :title="$title" />', ['title' => __('My field')]);
Run Code Online (Sandbox Code Playgroud)


小智 6

现在可以使用该Blade::renderComponent方法实现这一点。所以你应该这样做:

echo Blade::renderComponent(new Input('name', 'My field'));
Run Code Online (Sandbox Code Playgroud)


小智 1

我用这个,它也适用于匿名组件。将其放入您的帮助文件中。

/**
 * Render a blade component.
 * @param string $name Component name, exclude component folder (i.e use "card" instead of "components.card")
 * @param array $props Component properties
 * @param array $attributes Component attributes
 * @return \Illuminate\Contracts\View\View
 */
function viewComponent($name, $props = [], $attributes = []) {
    $className = collect(explode('.', $name))->map(function($part) {
        return \Str::studly($part);
    })->join('\\');
    $className = "App\\View\\Components\\{$className}";
    if(class_exists($className)) {
        $reflection = (new \ReflectionClass($className))->getConstructor();
        $parameters = [];
        foreach ($reflection->getParameters() as $param) {
            $parameters[] = $props[$param->name] ?? $param->getDefaultValue();
        }
        $component = new $className(...$parameters);
        $component->withAttributes($attributes);
        return $component->render()->with($component->data());
    }

    $props['attributes'] = new \Illuminate\View\ComponentAttributeBag($attributes);
    return view("components.$name", $props);
}
Run Code Online (Sandbox Code Playgroud)

用法

viewComponent('input', [
    'name' => 'name',
    'title' => 'My Field',
]);

// if you want custom attribute
viewComponent('input', [
    'name' => 'name',
    'title' => 'My Field',
], [
    'autocomplete' => 'off',
    'data-custom' => 'custom attribute',
]);
Run Code Online (Sandbox Code Playgroud)