Livewire use one component in a multiple time to update input fields - laravel

I'm using AlpineJs and Livewire in an application. I'm new to livewire, Here I want to Update the post name which is showing from a component inside another component. To reuse those I have separated those also there have lots of other features with complex logic.
Problem
The post name isn't changing, Not even fire the wire:model.
#post.table
#foreach ($posts as $index => $post)
<tr>
<td> {{ Str::limit($post->name, 22) }}</td>
<td> {{ $post->description }}</td>
<td> {{ $post->date }}</td>
<td> {{ $post->amount }}</td>
</tr>
<template x-if="some_condition">
<tr>
<livewire:post.post-details :post="$post" :index="$index">
</tr>
</template>
#endforeach
//pagination here
#post.post-details
class PostDetails extends Component
{
protected $post;
public $index;
public function mount($post, $index)
{
$this->post = $post;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-details', [
'post' => $this->post,
]);
}
}
<div>
<livewire:post.post-name :post="$post" :index="$index">
// Other components are here
</div>
#post.post-name
class PostName extends Component
{
public $post_name;
public $index;
protected $rules = [
'update_post.*.name' => 'required|string',
];
public function mount($schedule_entry, $index)
{
$this->post_name = $post->name;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-name');
}
public function some_action()
{
//
}
}
<div>
<input type="text" wire:model="update_post.{{ $index }}.name" wire:keydown="some_action" value="{{ $post_name }}">
</div>
If you guys have any better idea to reuse those component feel free to share. Thanks
I have try this two way
https://laravel-livewire.com/docs/2.x/properties#binding-models
https://laracasts.com/discuss/channels/livewire/livewire-save-fields-with-same-name

Related

Laravel : get data for user using relationships

Get user's answer , question in page by user id , i want to display table for each user contains his answers with questions
I tried to create show page and add show function in UserController
Controller :
public function show($id)
{
$user = User::find($id);
$user_id = $user->id;
$survey = \App\Survey::pluck('title', 'id')->toArray();
$answers = \App\Answer::where('user_id','=',$user_id)->get();
return view('users.show', compact('user','survey','answers'));
}
view:
<table class="table">
<thead class="thead-light">
<tr>
<th>{{ __('Question') }}</th>
<th>{{ __('Answers') }}</th>
<th>{{ __('Creation Date') }}</th>
</tr>
</thead>
<tbody>
#foreach($answers as $t)
<tr>
<td> {{ optional($t->survey)->title }} </td>
<td> {{ $t->answer }} </td>
<td> {{$t->created_at}} </td>
</tr>
#endforeach
</tbody>
</table>
Answer model :
class Answer extends Model
{
protected $fillable = ['answer','commentaire','user_id','survey_id','last_ip'];
protected $table = 'answer';
public function survey()
{
return $this->belongsTo('App\Survey', 'survey_id');
}
public function question()
{
return $this->belongsTo(Question::class);
}
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
}
user model :
public function questions()
{
return $this->hasMany(Question::class);
}
public function answers()
{
return $this->hasMany(Answer::class);
}
the tables :
answer :
Survey :
I got empty part for question row
You are performing some queries that you actually don't need.
First get rid of this to lines:
$user_id = $user->id; $survey = \App\Survey::pluck('title', 'id')->toArray();
Then change your query to get your answers:
$answers = \App\Answer::where('user_id','=',$user->id)->with(['survey'])->get();
return view('users.show', compact('user','answers'));
Now in your view you could just do this:
<td> {{ $t->survey->title }} </td>
<td> {{ $t->answer }} </td>
<td> {{$t->created_at}} </td>

Laravel - Error: App\Exports\View must be compatible with Maatwebsite\Excel\Concerns\FromView::view(): Illuminate\Contracts\View\View

I am trying to export to excel using PHP 7, Laravel 5.8, Maatwebsite Excel 3.1. I successfully display on the view blade and also perform the filter.
Model:
use App\UserResponse;
Controller
public function userresponseReport(Request $request,$export=false)
{
$data['title'] = 'User Response';
$userresponses = DB::table('user_response as g')
->select(
//DB::raw('DATE(g.created_at) as created_date'),
DB::raw('g.created_at as created_date'),
'g.msisdn',
'g.game_code',
'g.answer',
'g.answer_code',
'g.Amount_charged',
'g.payment_ref',
'g.status',
'g.user_channel'
)
->orderByRaw('g.created_at DESC');
$start_date = $request->start_date;
$end_date = $request->end_date;
$render=[];
if(isset($request->start_date) && isset($request->end_date))
{
$userresponses=$userresponses->whereBetween('created_at',[$start_date.' 00:00:00',$end_date.' 23:59:59']);
$render['start_date']=$request->start_date;
$render['end_date']=$request->end_date;
}elseif(isset($request->start_date))
{
$userresponses=$userresponses->where('created_at',$request->start_date);
$render['start_date']=$request->start_date;
}
if(isset($request->msisdn))
{
$userresponses=$userresponses->where('msisdn','like','%'.$request->msisdn.'%');
$render['msisdn']=$request->msisdn;
}
if(isset($request->game_code))
{
$userresponses=$userresponses->where('game_code','like','%'.$request->game_code.'%');
$render['game_code']=$request->game_code;
}
if(isset($request->user_channel))
{
$userresponses=$userresponses->where('user_channel','like','%'.$request->user_channel.'%');
$render['user_channel']=$request->user_channel;
}
if(!empty($export))
{
return Excel::download(new UserresponseExport($userresponses->get()), 'userresponse.xlsx');
}
$userresponses= $userresponses->orderBy('created_at','DESC');
$userresponses= $userresponses->paginate(15);
$userresponses= $userresponses->appends($render);
$data['userresponses'] = $userresponses;
return view('report.userresponseReport',$data);
}
Then after that, the view blade:
userresponseReport.blade.php
<div class="row" style="margin-bottom: 10px">
{{ Form::model(request(),['method'=>'get']) }}
<div class="col-sm-2">
{{ Form::text('msisdn',null,['class'=>'form-control','placeholder'=>'MSISDN']) }}
</div>
<div class="col-sm-2">
{{ Form::text('game_code',null,['class'=>'form-control','placeholder'=>'Game Code']) }}
</div>
<div class="col-sm-2">
{{ Form::text('user_channel',null,['class'=>'form-control','placeholder'=>'Channel']) }}
</div>
<div class="col-sm-2">
{{ Form::date('start_date',null,['class'=>'form-control','placeholder'=>'Date']) }}
</div>
<div class="col-sm-2">
{{ Form::date('end_date',null,['class'=>'form-control','placeholder'=>'Date']) }}
</div>
<div class="col-xs-2">
{{ Form::submit('Search',['class'=>'btn btn-warning']) }}
<i class="fa fa-file-excel-o"></i> Excel
</div>
{{ Form::close() }}
</div>
<div class="box box-primary">
<div class="box-header with-border">
<table class="table table-bordered table-hover table-striped table-condesed" id="commenter_info_table">
<caption></caption>
<thead>
<tr>
<td>#</td>
<td>Date</td>
<td>MSISDN</td>
<td>Game Code</td>
<td>Game Name</td>
<td>Answer</td>
<td>Channel</td>
</tr>
</thead>
<tbody>
#foreach($userresponses as $key => $userresponse)
<tr>
<td>{{ ++$key }}</td>
<!-- <td>{{ $userresponse->created_date }}</td>-->
<td>{{ date('Y-m-d h:i:s A', strtotime($userresponse->created_date)) }}</td>
<td>{{ $userresponse->msisdn }}</td>
<td>{{ $userresponse->game_code }}</td>
<td>
#if($userresponse->game_code=='101')
Trivia
#elseif($userresponse->game_code=='102')
Predict and Win
#elseif($userresponse->game_code=='103')
Party With the BBN
#elseif($userresponse->game_code=='104')
Grand Prize
#elseif($userresponse->game_code=='105')
Happy Hour
#elseif($userresponse->game_code=='106')
Power Boost
#endif
</td>
<td>{{ $userresponse->answer }}</td>
<td>{{ $userresponse->user_channel }}</td>
</tr>
#endforeach
<tr>
<td colspan="14">
{{ $userresponses->links() }}
</td>
</tr>
</tbody>
</table>
Then the Export
UserresponseExport
class UserresponseExport implements FromView, WithHeadings, ShouldAutoSize, WithEvents, WithMapping
{
protected $userresponses;
public function __construct($userresponses = null)
{
$this->userresponses = $userresponses;
}
public function view(): View
{
return view('report.userresponseReport', [
'userresponses' => $this->userresponses ?: DB::table('user_response as g')
->select(
DB::raw('g.created_at as created_date'),
'g.msisdn',
'g.game_code',
'g.answer',
'g.answer_code',
'g.Amount_charged',
'g.payment_ref',
'g.status',
'g.user_channel'
)
->orderByRaw('g.created_at DESC')
]);
}
private $headings = [
'Date Created',
'MSISDN',
'game_code',
'Answer',
'Channel'
];
public function headings(): array
{
return $this->headings;
}
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$cellRange = 'A1:E1'; // All headers
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(14);
},
];
}
}
Route
Route::get('/report/userresponse-report/{export?}', ['as' => 'userresponseReport', 'uses' => 'ReportController#userresponseReport']);
On the view blade, when I clicked on search everything was okay. But when I click on export, I got this error:
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_UNKNOWN)
Declaration of App\Exports\UserresponseExport::view(): App\Exports\View must be compatible with Maatwebsite\Excel\Concerns\FromView::view(): Illuminate\Contracts\View\View
What could have caused this error?
How do I resolve it?
This error indicates that your class App\Exports\UserresponseExport is not following the interface correctly.
By the error we can see that you need to have a method named view which you have, but your method have typehinted App\Exports\View as the return type instead of Illuminate\Contracts\View\View.
To fix this simply change your view method return type to Illuminate\Contracts\View\View.
Your code right now most likely says
public function view(): View
{
...
}
But as you are missing use Illuminate\Contracts\View\View; in your import statements, View is getting resolved to the current namespace of your class + the class you are trying to typehint, which results in App\Exports\View.
So another solution to this instead of typehinting the full namespace is to import Illuminate\Contracts\View\View, in your class by adding use Illuminate\Contracts\View\View; at the top of your file.

How to access model function in view or blade file

I want to get interest amount which is multiple of amount and interest rate in a table "loan". I want to call the value from a table and used for display loan information.
I have tried using mutators in which case gives same error as mentioned below
Loan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $fillable = ['amount', 'interest', 'status', 'member_id', 'loan_type_id', 'interest_type_id', 'loan_payment_type_id'];
public function getInterestAmountAttribute()
{
return $this->amount * $this->interest;
}
public function member()
{
return $this->belongsTo(Member::class, 'member_id', 'id');
}
}
loan.blade.php
<table class="table table-stripped">
<thead>
<tr>
<th>Loan Id</th>
<th>Amount</th>
<th>Interest</th>
<th>Interest Amount</th>
<th>Interest Type</th>
<th>Loan Type</th>
<th>Status</th>
<th>Payment Type</th>
<th>Member</th>
<th>Action</th>
</tr>
#foreach($loanData as $key=>$loan)
<tr>
<td>{{++$key}}</td>
<td>{{$loan->amount}}</td>
<td>{{$loan->interest}}</td>
<td>{{ $loan->interest_amount}}</td>
<td>{{$loan->interesttype->interest_type}}</td>
<td>{{$loan->loantype->loan_type}}</td>
<td align="center">
<span class="bg bg-primary" style="border-radius: 10px;padding:2px 5px">{{$loan->status}}</span>
<form action="{{route('update-loan-status')}}" method="post">
{{csrf_field()}}
<input type="hidden" name="criteria" value="{{$loan->id}}"/>
#if($loan->status== 1)
<button class="btn btn-success btn-xs" name="paid"><i class="fa fa-check"></i></button>
#endif
#if($loan->status== 0)
<button class="btn btn-danger btn-xs" name="unpaid"><i class="fa fa-close"></i></button>
#endif
</form>
</td>
<td>{{$loan->paymentmethod->method}}</td>
<td>{{$loan->member->name}}</td>
<td>
Delete
Edit
</td>
</tr>
#endforeach
</thead>
</table>
{{$loanData->links()}}
This gives the following error:
Method Illuminate\Database\Eloquent\Collection::links does not exist.
when I remove brackets
<td>{{$loan->getInterest}}</td>
the error is
App\Loan::getInterest must return a relationship instance.
LoanController.php
<?php
namespace App\Http\Controllers\Backend;
use App\Http\Controllers\Controller;
use App\Loan;
use App\Interest;
use App\LoanPaymentMethod;
use App\Member;
use App\Loantype;
use DB;
class LoanController extends Controller
{
protected $_backendPath = 'backend.';
protected $_pagePath = 'backend.pages.';
protected $_data = [];
public function index()
{
$loanData = Loan::orderBy('id', 'desc')->get();
$loanData = Loan::paginate(10);
$loanData = Loan::all();
$memberData = Member::all();
$loantypeData = Loantype::all();
$paymentmethodData = LoanPaymentMethod::all();
$interestData = Interest::all();
$this->_data['loanData'] = $loanData;
//$results = Loan::with('member')->get();
//$dat->loan = Loan::with('member')->get();
//$loan = Member::find($memberData)->loan;
return view($this->_pagePath . 'loan.loan', $this->_data);
//$userData = DB::table('members')->get();
//return view('home',compact('userData'));
}
}
Define your function as accessor in your Loan.php :
public function getGetInterestAttribute()
{
return $this->amount * $this->interest;
}
Now you can access it , like this :
<td>{{ $loan->get_interest }}</td>
The right way to call an Accessor,
public function getModifiedInterestAttribute() // first get then ModifiedInterest then Attribute
{
return $this->amount * $this->interest;
}
Then you can call the Accessor like below,
<td>{{$loan->modified_interest }}</td>
You can see this for more details : https://laravel.com/docs/5.8/eloquent-mutators#defining-an-accessor
You should append that variable in model data Like
class Loan extends Model
{
protected $appends = ['interest'];
}
Your accessor should like
public function getInterest()
{
return $this->amount * $this->interest;
}
Access in blade file as you use above
<td>{{$loan->interest}}</td>

Laravel view won't loop model even though it is populated

I'm creating a web based interface for my dovecot database.
I can get a list of all the virtual domains in the database and the number of emails and aliases easily enough.
But when I try to load a page to list the emails under a specific domain, it goes weird.
Three simple models:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VirtualDomain extends Model
{
public function emails()
{
return $this->hasMany('App\VirtualUser', 'domain_id');
}
public function aliases()
{
return $this->hasMany('App\VirtualAlias', 'domain_id');
}
}
class VirtualUser extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
];
}
class VirtualAlias extends Model
{
//
}
My default controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\VirtualDomain;
use App\VirtualUser;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home', [
'domains' => VirtualDomain::all(),
]);
}
public function domain($name)
{
$domain = VirtualDomain::where('name', $name)->first();
return view('domain', [
'domain' => $domain,
'emails' => VirtualUser::where('domain_id', $domain->id),
]);
}
}
and a couple of simple blades
home.blade.php
<p>
{{ $domains->count() }} domains
</p>
<table class="table-summary">
<thead>
<tr>
<th>name</th>
<th>emails</th>
<th>aliases</th>
<th class="table-summary-options">options</th>
</tr>
</thead>
<tbody>
#foreach ($domains as $domain)
<tr>
<td><a title="view emails for this domain" href="domain/{{ $domain->name }}">{{ $domain->name }}</a></td>
<td>{{ $domain->emails->count() }}</td>
<td>{{ $domain->aliases->count() }}</td>
<td class="table-summary-options"><a class="ui-action" title="remove this domain" href=""><img src="/img/ui/remove.png" alt="remove"></a></td>
</tr>
#endforeach
</tbody>
</table>
and domain.blade.php
<p>
<< - {{ $domain->name }} - {{ $emails->count() }} emails
</p>
<table class="table-summary">
<thead>
<tr>
<th>email</th>
<th class="table-summary-options">options</th>
</tr>
</thead>
<tbody>
#foreach ($emails as $email)
<tr>
<td><a title="view aliases for this domain" href="email/{{ $email->email }}">{{ $email->email }}</a></td>
<td class="table-summary-options"><a class="ui-action" title="remove this email" href=""><img src="/img/ui/remove.png" alt="remove"></a></td>
</tr>
#endforeach
</tbody>
</table>
The view outputs the correct number of emails under the domain with {{ $emails->count() }} - but the#foreach ($emails as $email)` does not loop.
When I modify the blade to simple use the emails from the domain variable ({{ $domain->emails->count() }} and #foreach ($domain->emails as $email)), I get the right count and the list is populated correctly.
What's making it go wrong when using the emails variable?
You have to make a small change for it to work
public function domain($name)
{
$domain = VirtualDomain::where('name', $name)->first();
return view('domain', [
'domain' => $domain,
'emails' => VirtualUser::where('domain_id', $domain->id)->get(),
]);
}
Without ->get() you will get a query builder instance while with get() will return a collection. In the foreach loop a collection can be iterated while a query builder instance can't be.
Hope this helps

returning null when getting the values of the paramater of create method in laravel

I have a custom route that accepts parameter. Which is:
Route::get('reservation/{id}/create',
['as' => 'reservation.create', 'uses' => 'ReservationController#create'
]);
I have this variable protected $student_id. That id is being assigned to the parameter of the create method of ReservationController as seen below:
class ReservationController extends Controller
{
protected $student_id;
public function index()
{
return $this->student_id;
}
public function create($id)
{
$this->student_id = $id;
$subjects = Subject::with('sections')->get();
return view('reservation.form',compact('subjects'));
}
public function store(Request $request)
{
$subject = new Reservation();
$subject->section_subject_id = $request->sectionSubjectId;
$subject->student_id = $this->student_id;
$subject->save();
}
}
When returning the $id parameter on the create method I get the exact id number. I also assigned that $id with the $student_id. But when assigning the $student_id on the store method I get null value. I know that I am doing wrong here, can someone please help me on this.
Okay, so let me add some information: In my url when using the reservation.create route I have this address localhost:8000/reservation/1/create
the number 1 in that url is the student id i want to get and assign to the student_id in my store method.
I also have this form view:
form.blade.php
<body>
#foreach($subjects as $subject)
#foreach($subject->sections as $section)
<tr>
<td>{{ $section->section_code }}</td>
<td>{{ $subject->subject_code }}</td>
<td>{{ $subject->subject_description }}</td>
<td>{{ $section->pivot->schedule }}</td>
<td>{{ $subject->units }}</td>
<td>{{ $section->pivot->room_no }}</td>
<td>
<button
v-on:click="addSubject( {{ $section->pivot->id }} )"
class="btn btn-xs btn-primary">Add
</button>
<button class="btn btn-xs btn-info">Edit</button>
</td>
</tr>
#endforeach
#endforeach
</body>
At the same time I make us of vue.js and vue-resource
all.js
methods:{
addSubject: function(id){
this.$http({
url: 'http://localhost:8000/reservation',
data: { sectionSubjectId: id },
method: 'POST'
}).then(function(response) {
console.log('success');
},function (response){
console.log('failed');
});
}
}
You're trying to save variable in $this->student_id and use it later in another method. This is not how this works. The thing is these methods are used in different HTTP requests, so variable will not be kept.
You should pass this variable with from the reservation.form view to the store() method.
You can use Request object for that. In a view:
<input name="studentId" type="hidden">{{ $studentId }}</input>
And in controller:
$studentId = $request->get('studentId');
Or you can pass it as second parameter if you want to use it in a store() method.
public function store(Request $request, $studentId)
{
echo $studentId;

Resources