【问题标题】:Render Laravel 7 component programmatically以编程方式渲染 Laravel 7 组件
【发布时间】:2020-08-12 11:52:35
【问题描述】:

我有一个 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');
    }
}

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

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

我需要在代码中创建和呈现字段,我尝试了以下方法:

$field = new Input('name', 'My field');
$field->render();

这会返回一个错误:

Undefined variable: title

我可以看到渲染函数被调用,但公共属性对视图不可用。如何使用公共属性渲染组件?

【问题讨论】:

  • 你的班级名称是什么?
  • 这个类叫做“Input”
  • 测试无害,所以将你的 laravel 更新到 7.9,你的代码如下: 如果它不起作用删除标题前的冒号
  • 该字段在 Blade 模板中渲染得很好,我需要知道如何以编程方式渲染它。我正在创建一个系统让用户创建自己的字段,我需要从代码而不是固定模板呈现它们。

标签: laravel laravel-blade laravel-7


【解决方案1】:

手动向视图添加变量。否则就不行了

我报告了这个,但它不被视为问题:

https://github.com/laravel/framework/issues/32429

【讨论】:

    【解决方案2】:

    只需手动添加要查看的属性即可。如果不将属性设为私有,但它不应该对此产生影响。只是我的实现。

         /**
         * Get the view / contents that represent the component.
         *
         * @return \Illuminate\View\View|string
         */
        public function render()
        {
            return view(
                'components.fields.input',
                ['name' => $this->name, 'title' => $this->title]
            );
        }
    

    【讨论】:

    • 这样你就失去了app/View/Components/*中的逻辑
    【解决方案3】:

    试试这个,它在 laravel 8 中对我有用,我检查了 data 函数存在于 laravel 7 中

    $field = new Input('name', 'My field');
    $field->render()->with($field->data());
    

    **数据函数包括组件的方法、属性和属性。

    【讨论】:

    • 这太棒了!谢谢!对于我的用例,我希望将输出作为字符串,所以我这样做了:$pre_rendered_component_as_html_string = $header_component->render()->with($header_component->data())->render();
    • @jakedowns 我也需要,但我发现最后调用toHtml() 更有诗意,至少在 Laravel 8 中完全一样:D
    【解决方案4】:

    我使用它,它也适用于匿名组件。把它放在你的帮助文件中。

    /**
     * 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);
    }
    

    用法

    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',
    ]);
    

    【讨论】:

      【解决方案5】:

      Laravel 的 last release (v.8.80) 应该可以帮助你实现你想要用 pull #40425 做的事情

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

      【讨论】:

        猜你喜欢
        • 2011-10-09
        • 1970-01-01
        • 2022-12-13
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-22
        相关资源
        最近更新 更多