Laravel: Conditional rendering with dynamic components not working - laravel

I want to have a dynamic component that can conditionally render child dynamic components.
Let's imagine having a parent component Parent.php
In my view blade this is then called something like this
(Of course, this wouldn't be parent but a method that resolves that name)
<x-dynamic-component :elements="$elements" component="parent" />
Within that component, based on the $elements variable, it should render other dynamic components
$element could be for instance Radio.php or Checkbox.php
So what I'm trying to do within my parent component is this:
<div>
#foreach($elements as $element)
#if($element->hasDynamicComponent())
<x-component-dynamic :component="$element->getComponentName()" />
#endif
#endforeach
The problem is, that Laravel nevertheless parses those lines regardless of this if statement.
I'm getting the following error message:
Unable to locate a class or view for component [component-dynamic]. (View: .....)
This is because $element->hasDynamicComponent() is false and therefore getComponentName is empty. Of course Laravel cannot resolve a component without a name.
The thing is Laravel shouldn't even try to resolve this, because hasDynamicComponent is false.

Related

Livewire validate nested component

I have a form on my TimesheetPaymentForm component. However I'd like to use a nested component ChecksForm inside the form
<x-cards.body>
<x-forms.row
wire: model="user.full_name"
errorName="user.full_name"
name="user.full_name"
text="Payee"
type="text"
disabled
>
</x-forms.row>
#livewire('checks.checks-form')
</x-cards.body>
Checks-form only has check-specific inputs and I don't want to use #include since I would have to duplicate the data and validation each time I use this in my app.
The data from the ChecksForm component is loading as expected in the TimesheetPaymentForm. However, since this data is nested in the main component, when it validates those on the TimesheetPaymentForm and I get an error saying the input is not in the rules to be valiaded.

Difference between #aware and #props directives in laravel 9

The #aware Laravel Blade template directive was introduced in Laravel 8, but I still don't understand what it does differently from the already existing #props directive.
For instance, if I use a Blade template like this:
<x-view-content :page="$page ?? ''" />
and the component used above is defined in views/components/view-content.blade.php like this:
#aware(['page'])
<div>
{{ $page }}
</div>
I get the page successfully rendered inside the component. However, replacing #aware(['page']) with #props(['page']) produces the same result.
I would like to know what the differences between them are.
#aware is for accessing data from a parent component where you have #props. You can find here all relevant information. In your case you don't have child component.

How to render multiple livewire component as string?

I have multiple livewire components e.g. opd.patient-count, opd.visit-count, opd.checkup-count and so on. I would like to store these components name into database then call by user role. Anyway, It does not work once I tried as below.
foreach ...
echo '<livewire:opd.patient-count />';
endforeach ...
Any advice or guidance on this would be greatly appreciated, Thanks.
As I understand your problem, You can achieve using this syntax instead
#foreach($components as $eachComponent)
#livewire($eachComponent,['componentData' => $data])
#endforeach
in this code above, the component name is assigned accordingly using a blade #foreach directive and iterate over each element and make the component.

Laravel check livewire component existence

I want to check if a livewire component exists before rendering. My program has modules and each client has some of those modules enabled. I can get the list of modules a client has with $client->getModules().
Each module can implement livewire components to enhance functions of the program. I want to render those components if they exist in the correct section of the program. For example in the user creation view, I would have this:
#foreach($client->getModules() as $module)
if( component_exists( $module . '::users.create' ) )
#livewire( $module . '::users.create' )
endif;
#endforeach
If the module implements something related to the user creation, it will have the livewire component users.create, but not all modules will enhance user creation. I need to assert the existence of the component before rendering it. I was wondering if there is something like component_exists( Component::class ), otherwise, I would love to see if someone could give me a hint in how to create it as a helper function.
You can take advantage of LivewireComponentsFinder class to check if component is in manifest :
app(LivewireComponentsFinder::class)->getManifest();
If you want to create a helper, I created laravel-helpers. So, you can create a helper like this:
function component_exists($class)
{
$manifest = app(\Livewire\LivewireComponentsFinder::class)->getManifest();
return (bool) array_search($class, $manifest);
}

Builder Plugin set identifier value through partial

I am trying to use output data that I have set up using the builder plugin through the Record Details component and running into some issues.
In my created plugin, Schools, I have Instructors (set up as a relation to an instructors plugin I created separately). It is possible to have more than one instructor, so they are store in the database as an array. Like so:
[{"instructor":"69"},{"instructor":"79"},{"instructor":"80"},{"instructor":"96"}]
The numbers represent the row ID of the instructor table
In my CMS I can pull all of the School info just fine into a partial (Builder Details), and can pull the array of instructors, but I am struggling to pass this array over to look up the ID and get the instructors information. My thought right now is to send it to another partial like so:
{% "school/instructor" insProfile = instructorID %}
The partial school/instructor is getting the ID just fine. I have included the Builder Details component and set it up with the following:
Alias: builderDetails
ModelClass: Instructors Plugin
Identifier value: insProfile
Key Column: id
Display Column: member_name
I am getting record not found results. I am confused as to how to set the Identifier Value to match the value I passed through my partial. I tried {% set identifierValue = insProfile %} before the {% set record = ... %} is run, but that did not work either.
I cannot use the :slug because that is already generating the content needed for the School page. In a TLDR, it seems I ultimately want to duplicate this function through another partial and a different tag.
Still learning October, so any help is appreciated.
I think the original post was a bit lengthy and ultimately what I wanted to do was pass a variable into a component. Such as:
{% component 'builderDetails' identifierValue=dynamicVar %}
This does not appear to work as the builder details component generates too far into page load to pick up the variable change.
Per the OctoberCMS docs, the best solution for me was to create my own component that would accept the variable before the page processed using onRender() function.
public function onRender()
{
// This code will be executed before the default component
// markup is rendered on the page or layout.
$this->profileID = $this->property('insProfile');
$this->ins = $this->getUserInfo($this->profileID);
}
This allows me to put my component in a partial, and request the partial with the variable 'insProfile'. The component will pick up the property insProfile before page/plugin generates and use that variable instead of the default.
I then set up another function to query the correct user info needed (getUserInfo)
It would be nice if the builder plugin components could be updated in such a way that I did not have to do this as the builder plugin is rather extensive out of the box.
Posting this in case anyone else comes along this problem and isn't sure where/how to pass a partial variable into a component.

Resources