Use blade value inside a component - php

At the moment I can successfully display some generated content in my blade view by calling a variable with a key, like this:
<div>
{{ $data['key'] }}
</div>
What I would like to achieve, is to reuse the key for a class name for example. The reason for that is that I want to easily access this content with JavaScript by using a selector. Something that would look like this:
<div class='key'>
{{ $data['key'] }}
</div>
This code work, but as I have many fields, I would like to avoid duplicating the key. To achieve that, I thought of creating a blade components, and pass the key in the slot. So that I can reuse this key both in the class name, and in the placeholder for data.
But it seems that my variable {{ $data }} is not accessible from my component file, as it throws the error: $data is undefined.
Here is my code:
<!-- In main.blade.php -->
#component('my-component')
key
#endcomponent
<!-- In my-component.blade.php -->
<div class="{{ $slot }}">
{{ $data[$slot] }}
</div>
I am not familiar to Blade so I am open to another approach if necessary.

You should pass your data and key as arguments to your component, thereby being more explicit. You don't need to use a slot for this, as a slot is generally used for blocks of text or HTML, not for simple attributes.
Create your component like this,
<div class="{{ $key }}">
{{ $data[$key] }}
</div>
And then render it like this
#component('my-component', ['data' => $data, 'key' => 'key'])

Related

How can I use a twig variable as a form field name

I have a form template which has a repeated block for several similar form fields. It is used as follows:
{# form_template.html.twig #}
{{ include ('company-select.html.twig', {field: 'companiesInclude'})
{{ include ('company-select.html.twig', {field: 'companiesExclude'})
{{ include ('company-select.html.twig', {field: 'companiesLinked'})
Now I have a company select template, which looks as follows:
{# company-select.html.twig (simplified, the actual template is much more complex) #}
<div class="form form-field selector" id="{{ field }}">
{{ form_label(form.field) }}
{{ form_widget(form.field) }}
</div>
The way it is, the template fails, because 'field' is not a property of the FormView class.
How can I make the template interpolate the twig variable into the form_xxx function call as an actual field name?
A property of an object or an array element in twig can either be accessed via the dot notation (.) or via the square bracket one ([]).
If your property happens to be a twig variable, you will need to use the later form.
So in your case:
form_label(form[field])
form_widget(form[field])
Your code in company-select.html.twig ending up being:
<div class="form form-field selector" id="{{ field }}">
{{ form_label(form[field]) }}
{{ form_widget(form[field]) }}
</div>
This is, in a really simplified example, testable here.
Note that, in a more complex flavour, you can also use the attribute function
., []: Gets an attribute of a variable.
Source: https://twig.symfony.com/doc/3.x/templates.html#other-operators
Also worth reading on the same note: https://twig.symfony.com/doc/3.x/templates.html#variables

assign $attributes in nested Laravel 7 blade components

With Laravel 7, I began to use View Components.
I am trying to pass the $attributes variable from one component to another like:
x-modal component:
<div {{ $attributes->merge(['class' => 'modal fade']) }}>
Something great...
</div>
x-modal-form component:
<x-modal {{ $attributes }}>
Something great too
</x-modal>
In this case, I have an id property in the x-modal component like:
<x-modal-form id="aRandomId" title="Test"></x-modal-form>
But in this case, the id aRandomId is not spread to the x-modal component. I have an error "syntax error, unexpected 'endif' (T_ENDIF), expecting end of file" because of {{ $attributes }}
Do you know how to do that?
This behavior has been fixed in Laravel 8: #32576
You can now pass the $attributes variable from one component to another
as per laravel documents :
All of the attributes that are not part of the component's constructor
will automatically be added to the component's "attribute bag". This
attribute bag is automatically made available to the component via the
$attributes variable. All of the attributes may be rendered within the
component by echoing this variable.
and in case of nested or use more than component in one view and want to use attribute bag so you put in this bag the common attribute and put manually unique attribute like so:
<x-modal {{ $attributes }}>
<x-modal-form {{ $attributes }} id="aRandomId" title="Test">
// code here
</x-modal-form>
</x-modal>
and of course, The id attribute specifies a unique id for an HTML element. The value of the id attribute must be unique within the HTML document.

How to pass a subview to a master view in Laravel?

I have a master view and depending on the URL and controller, it will load in another subview to a variable called $content, that's the idea.
Currently I am trying with:
return view("master")->with(["content" => view("pages.group")]);
So for example, if the URL is https://example.com/group/1 I am trying to get the subview included on my master template. Currently, it just gets escaped for XSS but I feel like this isn't the right way to do this?
I assume you are trying to display the sub-view content in the follwing way:
{{ $content }}
Change your syntax from {{ }} (Escaped output) to {!! !!} (Non escaped output).
{!! $content !!}
In the end after #lagbox mentioned it, using Laravel sections enabled me to use a master view and extend it when needed. https://laravel.com/docs/6.x/blade#extending-a-layout

Laravel Blade Template With Breadcrumbs

I have a template admin.blade.php that contains this code:
#yield('breadcrumbs', Breadcrumbs::render(Request::route()->getName()))
And in my child files I either ignore breadcrumbs or I would like to do something like:
#section('breadcrumbs')
{{ Breadcrumbs::render(Request::route()->getName(), $event) }}
#endsection
The problem is that it seems that the default yield content is still being triggered and when the function gets called I get an error.
Too few arguments to function
DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider::{closure}(), 1
passed in
C:\xampp\htdocs\msu\vendor\davejamesmiller\laravel-breadcrumbs\src\BreadcrumbsGenerator.php
on line 68 and exactly 2 expected (View:
C:\xampp\htdocs\msu\resources\views\event\station\edit.blade.php)
Which I understand, so my question is how do I achieve what I am trying to do in blade?
I also tried doing #section #show and section #stop but that seems to just hide the sections and give me the same error.
Any help is greatly appreciated.
You could create a component to handle the if case you are going to need:
<!-- resources/views/breadcrumb.blade.php -->
#if (isset($slot) && !is_null($slot))
#section ('breadcrumbs')
{{ Breadcrumbs::render(Request::route()->getName(), $slot) }}
#endsection
#endif
Then inside your child view, you can call your component:
<!-- resources/views/child.blade.php -->
#component('breadcrumb', ['slot' => $event]) #endcomponent
You can update the variable name in the component to whatever you like.
For more information about components: https://laravel.com/docs/5.6/blade#components-and-slots

Multiple #foreach in views - Laravel

I need to output various #foreach loops throughout my blade template, however they all target the same table in my database, just fetching different fields. As an example, I am using #yield in my main layout and #section in the views for title/descriptions tags etc etc:
#section('title')
#foreach($store_listings as $fetch)
Website stores - {{ $fetch->city }}, {{ $fetch->country }}
#endforeach
#stop
#section('description')
#foreach($store_listings as $fetch)
List of Stores in {{ $fetch->city }}, {{ $fetch->country }}.
#endforeach
#stop
Then in layout.main:
<title>#yield('title')</title>
and
<meta name="description" content="#yield('description')" />
This repeated #foreach loops are present in other sections of my views on other pages. I try to work by the DRY method. What are the suggestion here to save me entering multiple foreach loops when all I wish to do is call some variables? I don't want to have my controller to handle this business either.
Thanks
One thing you can do in this case it to use a partial, let's say views/_partials/storeList.blade.php:
#foreach($store_listings as $fetch)
{{$title}} {{ $fetch->city }}, {{ $fetch->country }}
#endforeach
Then in your main view you just call it:
#include('_partials.storeList', array('title' => 'Website stores -'))
#include('_partials.storeList', array('title' => 'List of Stores in'))

Categories