How to pass the parameter in InertiaJS? - laravel

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" >

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 livewire entanglement into Alpine component

I have a modal component which uses Alpine, which I made into a Blade component.
// Modal blade component
<div x-data="{ open = false }">
<div x-show="open"></div>
</div>
I want to share the open state with a Livewire component, but I don't know how to pass the #entangle directive through the component:
// Livewire component
<x-modal>
</x-modal>
I tried this:
// Modal Blade component
<div {{ $attributes }}>
<div x-show="open"></div>
</div>
// Livewire component
<div x-data="{ open = #entangle('livewire-state')}">
<div x-show="open"></div>
</div>
But the entangle directive just get parsed into string.
Your x-data object isn't properly syntaxed. You are using a = instead of a :. You should be seeing a console error also, if you happened to have the console open. Use the following syntax:
<div x-data="{ open: #entangle('livewire-state')}">
Read more on #entangle in the docs.

Multiple slots with the same name -Laravel Blade

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.

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.

Component inside the default slot

I am fairly new to Vue and currently am working on the first project with it.
I have encountered this problem which I cannot seem to find a solution for, I have "AuthPage.vue" component which has a slot for the message and default slot for content, once I put custom componen in my login.blade.php it should be prefilled in that slot but it says that custom element does not exist. If I replace slot inside .vue file with custom element it seems to be working perfectly. I am not sure what I am doing wrong.
AuthPage.vue
<template>
<div>
<div class="page-brand-info"></div>
<div class="page-login-main">
<img class="brand-img" src="/assets/global/images/logo.jpg">
<h3 class="font-size-24 text-center"><slot name="title"></slot></h3>
<slot name="message"></slot>
<slot></slot>
<footer class="page-copyright">
<p>© {{ moment().year() }}. All RIGHT RESERVED.</p>
</footer>
</div>
</div>
</template>
<script>
import LoginForm from './LoginForm.vue';
import ResetPasswordForm from './ResetPasswordForm.vue';
export default {
components: { LoginForm, ResetPasswordForm }
}
</script>
login.blade.php
#extends('backoffice.layout.auth')
#section('content')
<auth-page>
<template v-slot:title>Sign In</template>
<login-form></login-form>
</auth-page>
#endsection
Thank you for your help!
Eddie
You'll need to register the LoginForm component globally in order for it to be passed into the AuthPage component as a slot (when passed in directly from a view). This is because, outside the scope of your component, Vue doesn't know what <login-form> is.
Since you're using laravel, in your resources/js/app.js file add the following:
import LoginForm from './path/to/LoginForm.vue';
Vue.component('login-form', LoginForm);

Resources