How to pass array data from Laravel Inertia Js render method to child component from parent component in Vue 3? - laravel

I'm having users' array data and rendering this from route to Dashboard.vue component through inertia render method, where I'm unable to pass users data from Dashboard.vue component to Users.vue component.
Route::get('/dashboard', function () {
$users = User::all();
return Inertia::render('Dashboard', ['users' => $users]);
})->name('dashboard');
Dashbaord.vue parent component
<Users title="Hello world" users="{{ $users }}"></Users> //this one passing {{ $users }} as string data in props.
<Users title="Hello world" :users="{{ $users }}"></Users> //this one getting syntax error.
Users.vue child component
<template>
<div>
<h1>Component Displayed</h1>
<p>{{ title }}</p>
<ul v-for="user in users" :key="user.id">
<li>{{ user.name }}</li>
</ul>
</div>
</template>
<script>
export default{
props:{
users:Array,
title:String
}
}
</script>
Can anyone suggest to me how to pass array data from one component to another component in Vue js?

Have you tried <Users title="Hello world" :users="{{ users }}"></Users> in the parent?
(users, not $users)

:users="$page['props']['users']" worked.

Related

Get media collection spatie media library using inertia js

I'm using Spatie media library and I can upload images to storage and database. And I'm trying to display a media collection in a Vue component. This is my Controller:
public function showHotelPhoto($id)
{
$hotel = Hotel::with('media');
return Inertia::render('AdminHotelPhoto', [
'data' => $hotel,
]);
}
And this my Vue component:
<template>
<breeze-authenticated-layout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Foto Hotel
</h2>
</template>
#foreach ($hotel as $hotels)
#foreach ($hotels->getMedia('property_images') as $image)
<div class="-item">
<img src="{{ asset($image->getUrl()) }}">
</div>
#endforeach
#endforeach
</breeze-authenticated-layout>
</template>
<script>
import BreezeAuthenticatedLayout from '#/Layouts/Authenticated'
export default {
components: {
BreezeAuthenticatedLayout,
},
props: ['data'],
}
</script>
I know using #foreach can throw an error, but this is only for illustration. I want to loop get media collection in the Vue component.
You should use v-for instead of #foreach.
When you say with media, the media is returned as an array. You can access the path of the image with the original_url parameter in the directory.

property does not refresh in the internal components of Livewire

Take a look at the following examples:
showPost.blade.php:
<div>
<livewire:content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
and
content-box.blade.php :
<div>
<h1>{{ $content->title }}</h1>
<p>{{ $content->content }}</p>
</div>
So far, it is completely clear what is going to happen ...: First, the information of the content to be viewed is received through showPost and passed to the contentBox, and everything is OK ..
Well now I want to get the information of the next content via the account through the button I put and calling the nextPost method:
class ShowPost extends Component
{
public Post $post;
public function render()
{
return view('livewire.show-post');
}
public function nextPost()
{
$id = $this->post->id;
$nextPost = Post::where('id', '>', $id)->first();
$this->post = $nextPost;
}
...
But nothing happens and the contentBox component has no reaction .... Has anyone had this problem ???!
I'm not sure livewire works well with nested components. could use the pagination instead. The livewire docs suggest you should not use them for little snippets or use blade components for that kind of nesting.
You can achieve what you're doing at the moment with some simple pagination.
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
class SomeContent extends Component
{
use WithPagination;
public function render()
{
// Using simplePaginate(1) instead of paginate(1).
// simplePaginate only shows "<- Previous" and "Next ->" links
// paginate shows those 2 buttons but also page numbers which you don't seem to want.
return view('livewire.some-content', [
'users' => User::simplePaginate(1),
]);
}
}
<div>
{{-- This might look wrong, but essentially it's looping through an array of length 1 because we're paginating --}}
#foreach ($users as $user)
<h1>{{ $user->name }}</h1>
<h2>{{ $user->email }}</h2>
#endforeach
{!! $users->links() !!}
</div>
EDIT
I can confirm blade components work.
Here, nextUser is the same implementation you gave.
public function nextUser()
{
$id = $this->user->id;
$nextUser = User::where('id', '>', $id)->first();
$this->user = $nextUser;
}
<div class="container">
<div class="content">
{{-- These two have the exact same template --}}
<livewire:child :user="$user" />{{-- Doesn't update when clicking Next --}}
<x-blade-child :user="$user" />{{-- Updates when clicking Next --}}
</div>
<div>
<button wire:click="nextUser">Next</button>
</div>
</div>
When clicking nextUser, the blade component updates but the livewire one doesn't.
Livewire doesn't like nested components. In your case, we can use basic blade component:
<div>
<x-content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
And then:
Move content-box.blade.php to resources/views/components/
Remove component_name.php file in app/Http/Livewire
Most of the time, we can change 2 nested livewire components to livewire(parent) + basic blade component(child),

Laravel pass data to vue component

I'm passing through data from laravel into my vue component in order to be able to use VueJS however in my for each statement, the loop ends after the first set of data and does not show everything.
<div>
<v-card-title>{{course}}</v-card-title>
<v-card-subtitle>{{school}}</v-card-subtitle>
</div>
<script>
export default {
name:"InputForm",
props: ['course', 'courseGroup', 'school'],
}
</script>
This is the blade code that im using to pass data to vue
#foreach ($modules as $module)
<input-form
:course="'{{$module->Course}}'"
:school="'{{$module->School}}'"
/>
#endforeach
use json_encode() function to send data to vuejs
#foreach ($modules as $module)
<input-form
:course="{!! $module->Course !!}"
:school="{!! $module->School !!}"
/>
#endforeach

laravel rendering section no passing parameters data

i have a problem passing variable during the rendering of only a section
All works good but array of data passed to the section('sidebar') view create an error ($data doesn't exist)
My blade files are
Default.blade.php
..other html code before..
<body>
#include('includes.header')
<div class="container-fluid">
<div class="row">
#yield('sidebar')
<!-- main content -->
#include('includes.main')
</div>
<footer class="row">
#include('includes.footer')
</footer>
</div>
</body>
..other code after..
home.blade.php
#extends('layouts.default')
#section('sidebar')
#include('includes.sidebar')
#stop
sidebar.blade.php
..other html code before..
<h2>The current UNIX timestamp is {{ time() }}.</h2>
<ul>
#isset($data)
#foreach ($data as $item)
<li class="nav-item"> {{$item->polizza}}</li>
#endforeach
#endisset
</ul>
..other html code after..
Controller Method search
public function search(Request $request){
if ($request->ajax()) {
$data = Customers::select('id','contr_nom','email','targa','cliente')
->where('polizza',request('polizza'))
->get();
return view('pages.home',$data)->renderSections()['sidebar'];
}
//return json_encode($data);
}
I know that array $data is good because i try return just JSON and i know that just sidebar refresh because timestamp change.
But $data is not passed to sidebar section refreshed!!
Why?
Thks a lot
You have the right idea, you just need to send the variable in a form that will be recognized. I'll break it out to an extreme, to help understand the parts, but you can easily recombine for shorter code.
$view = view('pages.home', compact('data')); // Compact with the text name ('data') sends the variable through
$sections = $view->renderSections(); // returns an associative array of 'content', 'pageHeading' etc
return $sections['sidebar']; // this will only return whats in the sidebar section of the view
Using compact() should get your where you need, and is the key.

I cant display data from laravel api

I am trying to get data from my laravel app, and display it in Vue CLI.
I see the Response, but I can not display it in the VUE application.
When i do get to example API it's works, but not from my laravel server.
<template>
<div id="app">
<h1>{{ results }}</h1>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return{
results: null
}
},
mounted() {
axios.get('http://127.0.0.1:8000/api/')
.then(response => {
this.results = response.data.results
})
}
}
</script>
Your results are being received as an array of objects, a JSON encoded Laravel collection. You need to single out the object you want to display, and then a property of that object.
<div id="app">
<h1>{{ results[0].name }}</h1>
</div>
However, you should really only be returning one object if this is the case from your controller method, not an array of objects. (e.g., ->first() instead of ->get())
<div id="app">
<h1>{{ result.name }}</h1>
</div>
Collections are generally for displaying multiple results in lists, table, options, etc.:
<div id="app">
<ul>
<!-- v-for will loop through results -->
<li v-for="(result, index) in results">{{ result.name }}</li>
</ul>
</div>
EDIT:
Also, your results declaration needs to be adjusted according to the Network response.
this.results = response.data.results;
Should be:
this.results = response.data;
Or alternatively, your controller response needs to be:
return response()->json(['results' => $results]);
The answer was Cross-Origin Resource Sharing.
To connect laravel API with front-end i need to do add barryvdh/laravel-cors by composer.
composer require barryvdh/laravel-cors
Next add middleware in app/Http/Kernel.php to enable using API outside laravel APP. In my problem to Vue Cli.

Resources