Multiple slots with the same name -Laravel Blade - laravel

Assuming I want o make a new Blade Component called multi-step-form. I want the component to be able to have as many as possible forms slots. How do I achieve this.
I tried this: But it didn't work:
<!--resources/views/multi-step-form.blade.php -->
<div>
#foreach($forms as $form)
<div class="form"> {{ $form }} </div>
#endforeach
<x-next-button> <x-prev-button>
</div>
And in the child:
<x-multi-step-form>
<x-slot name="forms" {{ -- or "forms[], none of them work --}}>
<!-- Some form --->
<x-slot name="forms">
<x-slot name="forms" >
<!-- Some form --->
<x-slot name="forms">
<x-slot name="forms">
<!-- Some form --->
<x-slot name="forms">
</x-multi-step-form>
Am I missing something here?

this is not possible using blade, you can do something like this in vuejs but unfortunately for now it is not possible in laravel blade.
my suggestion would be to make a child component for this component instead of a slot so it would be reusable as much as you want.

Related

how to pass callback function in component? (laravel alpine.js)

I make a draft implementation for my reusable input component.
The code below obviously throws an error.
Question is how to pass the $event back to register blade to get or log the value of the input?
register.blade.php
<div>
<x-input onChange="(value) => {console.log('value', value)}"></x-input>
<div/>
input.blade.php
#props(['onChange' => 'null'])
<input x-on:change="{{ $onChange($event) }}">
A few things here.
First off, your markup is wrong. You have a the closing slash at the wrong end of the closing div. Should be </div> not <div/>.
Then you're using x-on without x-data. Alpine only picks up components with the x-data attribute.
Finally, events propagate automatically, so you could just listen on the parent instead:
{{-- register.blade.php --}}
<div x-data>
<x-input x-on:change="console.log('value', $event.target.value)" />
</div>
{{-- input.blade.php --}}
<input {{ $attributes }}>
I learned we could just achieve this through Alpine.Js dispatch. I don't need to pass onClick props via Laravel component. I just simply use dispatch to listen the event (x-on).
What I like in this implementation is that,
aside of event information, passing of extra data is easy
you don't have to use Laravel props and assigned unnecessary props in the tag.
register.blade.php
<div>
<x-input x-on:custom-input="console.log('your values =', $event.target.newValue)"
></x-input>
<div/>
input.blade.php
<input x-on:change="$dispatch('custom-input', { newValue: $event.target.value })">
you can pass "key" prop to distinguish each component.

How to pass the parameter in InertiaJS?

I got a problem with how the URL appeared in the browser after I have set up a route and call it through Inertia .
The route Route::get('/blogs/{post}', [BlogController::class, 'show']); from web.php works fine if I input it manually, e.g. localhost:3000/blogs/1.
However, the <Link> would not work if I click the button, instead the URL is displayed as http://localhost:3000/blogs/?post=1. Is there anyway to remove the ?post= from the URL?
Below is my Vue component displaying the <Link>
<div class="wrapper" v-if="blogs.length">
<div class="blog" v-for="blog in blogs" :key="blog">
<Link href="/blogs/" :data="{post:blog.id}">
<small>posted by: {{ blog.id }}</small>
{{ blog.title }}
</Link>
<button type="button" #click="destroy($event, blog.id)">
Delete post
</button>
</div>
</div>
Note that I am following the docs from https://inertiajs.com/links.
The problem is that you're passing the data prop. This will cause the object to be passed as the payload of the request. That's why it is ending up appended to the route as a query string.
// change this
<Link href="/blogs/" :data="{post:blog.id}">
// to this
<Link href="/blogs/your-blog-id-goes-here" >

2 way binding with Vue3 Inline template (using slots) in laravel blade template files

In Vue3, inline-templates were depreciated and now slots are used. Is it possible to have 2-way binding of variables for Vuejs components written in blade templates?
I want to have 2-way binding for Vue components that's written inline with blade templates. Although I know I can pass data like <example-component name="Hello World"> It is a ton of work to add props everywhere.
Vue recommends using slots as a inline-template replacement since it got removed in v3, however, that documentation makes no sense. I've got the components displayed using the code below. It's a dead simple text field + paragraph to display the name.
home.blade.php (Removed unnecessary HTML for brevity)
<div>
<h1>Dashboard</h1>
<example-component>
<div class="container">
<input v-model="name" placeholder="Change Name"/>
<p> Name is #{{ name }} </p>
</div>
</example-component>
</div>
example-component.vue
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
name: 'hi',
}
}
}
</script>
Unfortunately, this does not work, the name doesn't start as 'hi' and doesn't update when changing the textfield. When I try something like <slot :name=name></slot>. Which I believe would pass the name into the slots section, the component gets rendered for a second before disappearing.
Is having 2-way binding with vue variables in blade templates even possible? Any help is appreciated.
Vue: 3.0.5
Laravel: 8.29.0
Is there a reason you're storing the data in the child component? The reactivity design works by passing props down and emitting events up, even though (unfortunately) the reactivity is not maintained when passing a variable up to the parent component. Seems a little counter intuitive, but I might be missing something in what you're trying to create.
It will, however, work if you put the data into the app instead of the component.
// app
const app = Vue.createApp({
data() {
return {
name: 'hi',
}
}
})
// component
app.component('example-component', {
template: `
<div>
<slot></slot>
</div>`,
})
app.mount("#app");
<script src="https://unpkg.com/vue#3.0.5/dist/vue.global.prod.js"></script>
<div id="app">
<h1>Dashboard</h1>
<example-component>
<div class="container">
<input v-model="name" placeholder="Change Name"/>
<p> Name is #{{ name }} </p>
</div>
</example-component>
</div>
<!--

Laravel 8 Livewire component Undefined variable: header

I have created a Livewire component in Jetstream and I have set it as a full-page component in the web.php route page as follows:
use App\Http\Livewire\PostComponent;
...
Route::get('posts/',PostComponent::class)->name('posts');
The post-component.blade.php file has originally the following code:
<div>
<h1>If you look to others for fulfillment, you will never truly be fulfilled.</h1>
</div>
If I hit the URL .../posts I get the following error:
Undefined variable: header (View:
/home/vagrant/laravelapp/resources/views/layouts/app.blade.php)
So I have tried adding the slot in the post-component.blade.php file:
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div>
<h1>If you look to others for fulfillment, you will never truly be fulfilled.</h1>
</div>
</x-app-layout>
Nevertheless, I get that same error.
What am I missing? How do I fix this?
I hope this is a Jetstream project. By default, livewire will use the app.blade.php as the layout. And the component will get rendered in the slot of the app.blade.php.
But since it's a Jetstream project, it has a slot for the header in the layout file.
<header class="bg-white shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
</header>
So to resolve this error, there are two approaches.
give the header as the variable for the layout as below in your PostComponent.php
public function render()
{
return view('livewire.post-component')
->layout('layouts.app', ['header' => 'Post Compoent Page']);
}
Create your own layout and only have a slot. (imagine mylayout.blade.php)
<head>
#livewireStyles
</head>
<body>
{{ $slot }}
#livewireScripts
</body>
and use that layout when rendering the livewire component
public function render()
{
return view('livewire.post-component')->layout('layouts.mylayout');
}
There is a github issue regarding this topic (a closed one). But keep an eye on it. since Jetstream is in it's early stages.

How to give data from laravel to vue.js?

When i start write application i used to laravel blade. But now i have to transfer all to vue js and i don't known how to give data from controllers to vue.js. Also i don't know how to transfer this code
#if(Session::has('error_text'))
<div class="col-md-6 col-md-offset-3 formMessage">
<div class="iw">
<div class="text-error">{{Session::get('error_text')}}</div>
#if(Session::has('with_link'))
<div class="help-text">{{Session::get('link_text')}}</div>
#endif
#if(Session::has('unknown_symbols'))
<div class="help-text">Report a bug</div>
#endif
</div>
</div>
#endif
In the blade file if you want to access the vue data you should use #{{ item }}. With the # sign before the interpolation you escape the blade templating.
To pass data from the laravel to vue itself, you should use JSON which you call from your Vue and assign it to a variabel.
The best way to do this is by creating a component and assign the data with properties
<custom-component data="{{ $bladeVariable }}"></custom-component>

Resources