I'm using Laravel Livewire in my project, I use wire:loading for loading the state while clicking. I iterated all the tasks in foreach loop but the loading state applies for all components. Here is the code.
Blade file
GitLab: https://gitlab.com/tasklog/tasklog/-/blob/master/resources/views/livewire/home/tasks.blade.php
<button type="button" wire:click="togglePraise({{ $task->id }}, {{ $task->user->id }})">
👏
<span class="small text-black-50 font-weight-bold">
{{ $task->task_praise->count() }}
</span>
<div wire:loading wire:target="togglePraise">
Processing...
</div>
</button>
Controller file
GitLab: https://gitlab.com/tasklog/tasklog/-/blob/master/app/Http/Livewire/Home/Tasks.php
public function togglePraise($id, $user_id)
{
if (Auth::check()) {
if (Auth::user()->id === $user_id) {
session()->flash('message', 'Forbidden!');
return;
}
$isPraised = TaskPraise::where([
['user_id', Auth::user()->id],
['task_id', $id],
])->count();
if ($isPraised === 1) {
TaskPraise::where([
['user_id', Auth::user()->id],
['task_id', $id],
])->delete();
return true;
} else {
TaskPraise::create([
'task_id' => $id,
'user_id' => Auth::user()->id,
]);
return true;
}
} else {
return session()->flash('message', 'Forbidden!');
}
}
I know the question was before the realease of v2, yet adding the answer for v2 for reference.
as per the Livewire docs if you're using v2, you may specify the action and its parameters in the wire:target directive. For your example, it would be like this:
wire:target="togglePraise({{ $task->id }}, {{ $task->user->id }})"
I was unable to do it by loading targets to actions with parameters so I used jquery with the livewire
Button in the table loop with default d-none loading icon class
<div class="col-3">
<button class="btn btn-sm btn-default btn-save ">
Save <span class="loading-icon d-none">
<i class="fa fa-circle-o-notch fa-spin" style="font-size:14px"></i></span>
</button></div>
Javascript code to call livewire and enable loading
$('.btn-save').click(function (e) {
e.preventDefault();
$('.parameter-value').removeClass("error-field");
var row = $(this).closest('tr');
row.find('.loading-icon').removeClass('d-none');
var parameter = row.data('parameter');
var value = $.trim(row.find('.parameter-value').val())
if(value == ""){
row.find('.parameter-value').addClass('error-field');
}else{
row.find('.parameter-value').removeClass('error-field');
//Livewire call
#this.addParameterValue(parameter,value);
}
});
before LiveWire function ends dispatch browser event
public function addParameterValue($parameterID,$value)
{
...
$this->dispatchBrowserEvent('parameter_value-saved');
}
Handle Browser event from javascript end and remove hide loading icon inside
window.addEventListener('parameter_value-saved', event => {
$('.loading-icon').addClass('d-none');
})
I had the same issue as you. After researching, I decided to make 2 wire:click, IDK if this is the best way to solve this but yeah that's what I do
<div wire:loading wire:target="LoadingAnimation({{$loop->iteration}})">
// icon loading or teks for showing this row load sth
</div>
......
<div wire:click="LoadingAnimation({{$loop->iteration}})">
<a wire:click="setUpdateid({{$author->id}})">
// your content here , teks or maybe an icon
</a>
</div>
If you have any questions let me know, Happy coding!
Edit: Don't forget to make the method inside the class, like the LoadingAnimation and the setUpdateid
Related
So I have this problem with my Laravel project that I'm working on right now when I'm trying to store one data to the database but in the view, it shows five of it. And whenever I add another data. It won't stack. Kind of confusing, ain't it?
So What I'm actually trying to do is that I have 2 Models and is trying to overlap them to each other. As I search for ways to make them show in one view, I concluded in putting them into one Controller.
I made their Store CRUD separate so that it would work and this is how it looks like:
public function groupStore(Request $request)
{
$request->validate([
'title'=>'required',
'subject'=>'required',
'section'=>'required',
'team'=>'required',
'advisor'=>'required',
]);
GroupProject::create($request->all());
return redirect()->back()->with('success', 'Created Project Successfully.');
}
public function projectStore(Request $request)
{
$request->validate([
'title'=>'required',
'file'=>'required',
'description'=>'required',
]);
$file = $request->file('file');
$fileName = time().'_'.$file->getClientOriginalName();
$file->move(public_path('files'), $fileName);
$data = array(
'title'=>$request->title,
'file'=>$fileName,
'description'=>$request->description
);
Project::create($data);
return redirect()->back()->with('success', 'Posted Project Successfully.');
}
And here is how the Show CRUD looks like:
public function show(GroupProject $group_projects, Project $projects, $id)
{
$group_projects = GroupProject::find($id);
$projects = Project::find($id);
if (auth()->user()->type == 'faculty') {
return view('faculty/project', compact(['group_projects', 'projects']));
}else if (auth()->user()->type == 'office') {
return view('office/project', compact(['group_projects', 'projects']));
}else{
return view('student/project', compact(['group_projects', 'projects']));
}
}
PS: I'm trying to have Three users which makes the if else statements.
Now here's where the real problem comes from. As I make the "Group Project", I made the view with a foreach loop in order to show everything from my datastore, such as this and the corresponding program for it looks like this:
#foreach($group_projects as $key => $groupProject)
<div class="col flex">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title">{{ $groupProject->title }}</h3>
<h6>{{ $groupProject->subject }}</h6>
<h6>{{ $groupProject->section }}</h6>
<h6>{{ $groupProject->team }}</h6>
<h6>{{ $groupProject->advisor }}</h6>
<div class="dropdown">
<button id="dropdownMenu" class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ __('Actions') }}
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu">
<li><a class="dropdown-item" href="{{ URL::to('project/' . $groupProject->id) }}">
{{ __('Show')}}
</a></li>
</ul>
</div>
</div>
</div>
</div>
#endforeach
On this case, there seems to be no problem at all and it works perfectly fine even if I try to add another one.
But as I try to click it and change the view, this would be how it looks like after storing a "Project" and here's its corresponding Code:
#if (is_array($projects) || is_object($projects))
#foreach($projects as $key => $project)
<div class="col flex my-2">
<div class="card">
<div class="card-body">
<h3 class="card-title">{{ $projects->title }}</h3>
<iframe src="/files/{{ $projects->file }}"></iframe>
<h6>{{ $projects->description }}</h6>
</div>
</div>
</div>
#endforeach
#endif
And after adding another "Project" it will not show up on the "Test Title 1" but instead in "Test Title 2" which is pretty frustrating.
At first I'm thinking that it might be because I made the if statement of "#if (is_array($projects) || is_object($projects))" but if I remove this part, it would show an error when I'm trying to view a "Group Project" While there's nothing in the "Project" yet.
Another is that after making the foreach loop "#foreach($projects as $key => $project)" , I still call the "$projects->title" instead of "$project->title". but the reason for this is that it shows an error of "Attempt to read property "title" on bool".
I wonder, what should I do?
EDIT:
Nevermind Guys, I actually solved it just now.
So the real problem was on my Show CRUD. Instead of listing it as
$group_projects = GroupProject::find($id);
$projects = Project::find($id);
I should've called it as
$group_projects = GroupProject::find($id);
$projects = Project::all();
And Everything will be solved lol..... Now my problem is how to overlap them into one another such as 1 "Group Project" can have multiple "Project"....
My web doesn't seem to be directing to the correct page.
Here is my blade
<div class="container">
<div class="col-lg-12 d-flex justify-content-between align-items-center">
<h2>Informations</h2>
<a href="{{ route('add-new-information') }}" class="btn text-success">
<i class="fas fa-plus-circle fa-2x"></i>
</a>
</div>
<hr>
<div class="row d-flex justify-content-center align-items-center mt-5" style="max-height: 500px !important; overflow-y: scroll">
#foreach ($informations as $info)
<div class="card col-sm-11 p-0 mb-4 clickable-item" onclick='window.location = "{{ route('admin-informations', ['id' => $info->id]) }}"'>
...
</div>
#endforeach
</div>
</div>
Here is my routes/web
Auth::routes();
Route::group(['middleware' => ['auth'], 'prefix' => '/',], function () {
Route::get('/', function () {
return redirect('/home');
});
Route::group(['prefix' => 'admin'], function() {
Route::get('/informations', [App\Http\Controllers\InformationController::class, 'index'])->name('informations');
Route::get('/informations/{id}', [App\Http\Controllers\InformationController::class, 'indexAdminInfo'])->name('admin-informations');
Route::get('/informations/add-new-information', [App\Http\Controllers\InformationController::class, 'add'])->name('add-new-information');
});
});
and here is my controller
public function indexAdminInfo($id){
$information = Information::find($id);
// $comments = Comment::where('information_id', $id)->orderByDesc('created_at')->get();
$ack_count = Acknowledge::where('information_id', $id)->count();
$user_ack = Acknowledge::where([
['information_id', '=', $id],
['user_id', '=', Auth::user()->id],
])->first();
$ack = 'FALSE';
if($user_ack != null){
$ack = 'TRUE';
}
return view('adminviews/infoadmin', compact('information', 'ack_count', 'ack', 'user_ack'));
}
public function add(){
return view('adminviews/addinfo');
}
For some reason, when I click the a tag with the href {{ route('add-new-information') }} to go to the add page 'adminviews/addinfo',
instead the page will go to the 'adminviews/infoadmin' page, which will cause an error, because no parameters are being sent.
I tried checking the code, but it looks correct to me. Can anybody find an error on this?
the problem is with your routes:
these two routes are ambiguous:
Route::get('/informations/{id}');
Route::get('/informations/add-new-information');
just think of below scenario:
router wants to route, this url : /information/add-new-information
router will hit the first defined route, because it is compatible with the definition ('/informations/{id}')
Note :{id} is a variable and can be any string
so it will go with this.
Solution
write the more restricted route first,
and more general route later:
Route::get('/informations/add-new-information');
Route::get('/informations/{id}');
I'm working with Laravel 5.1
I have a template for a page that was previously working fine. I could hit my route and the page would be rendered as expected. At some point the page started just displaying the text contained in the blade template rather than rendering my page. To my knowledge nothing had changed in my routes file, controller or blade. Is there anything that is known to cause this to happen? I've tried updating permissions, using a different method to call the view and creating a new view file all together.
The route:
Route::group(['prefix' => '/admin'], function() {
Route::group(['prefix' => '/reactor-rules'], function() {
Route::get('/visual-rules/{track_id?}', [
'as' => 'broker_visual_reactor_rules',
'uses' => 'ReactorRulesController#visualRules'
]);
});
});
ReactorRulesController#visualRules:
public function visualRules(IReactorTrackDAO $reactorTrackDAO, $id = 0)
{
$export = new ReactorExport();
$tracks = $export->getReactorTracks();
if ($id == 0) {
$eventsArray = [];
}
else {
$eventsArray = $export->getArrayForTrack($id);
}
return $this->renderView('enterpriseBroker::reactor-rules.visual-rules', compact('eventsArray','tracks','reactorTrackDAO'));
}
My blade:
#extends($layout)
{{ SEO::setPageTitle(trans('enterpriseBroker::reactorRules.title'), false) }}
#section('content')
<br>
<br>
#if(empty($eventsArray))
<p>Please select a track below to view/export rules.</p>
#foreach($tracks as $track)
{{$track->name}}<br>
#endforeach
#else
#foreach($eventsArray as $track => $events)
<h4>{{$track}}</h4>
<a href="{{url().'/admin/visual-rules/'.$reactorTrackDAO->findByName($track)->id.'/download'}}" class="btn btn-primary" download>Export</a><br>
#foreach($events as $id => $event)
#if (count($event['rules']) > 0)
<div id="{{$track.'-'.str_replace(' ','_',$event['name'])}}">
<div class="col-lg-12">
<hr/>
<div class="col-lg-2">
<h4>{{$event['name']}}</h4>
</div>
<div class="col-lg-10 border border-primary">
#foreach($event['rules'] as $ruleId => $rule)
<h5>{{$rule['name']}}</h5>
<div class="col-lg-6">
<h6>Conditions to be met:</h6>
#foreach($rule['conditions'] as $condition)
<p>{{$condition}}</p>
#endforeach
</div>
<div class="col-lg-6">
<h6>Actions to run:</h6>
#foreach($rule['actions'] as $action)
<p>{!!$action!!}</p>
#endforeach
</div>
#endforeach
</div>
</div>
</div>
#endif
#endforeach
#endforeach
#endif
#endsection
#section('scripts')
#endsection
This is how it originally appeared:
This is how it currently appears:
It seems to be error with $layout
Try to test it using a hard coded value as below:
#extends('layouts.app')
and run below command
php artisan view:clear
I resolved the issue by creating a new blade file, pasting the contents of the old one in and pointing my controller to the new view. I'm not sure how this resolved the issue.
I have 2 questions and I need your help.First of all, I have made a delete route for comments, but other users logged can also delete comments from direct link...link.com/deleteComment/id. How to make this available only for owner of the comment?The owner id is saved in database and can be accessed with {{ $comment->user_id }}.
Second problem...In my view, when I click on a photo which have no comments, I'm receiving undefined variable comment, but I dont know why because on photos with comments, I have no problem with that.Can I make something like if comments != empty, dont show it or something like that?
CommentsController:
public function store(Request $request, $post_id)
{
$this->validate($request, array(
'comment' => 'required|min:5|max:2000',
));
$post = Post::find($post_id);
$comment = new Comment();
$comment->username = Auth::user()->username;
$comment->email = Auth::user()->email;
$comment->user_id = Auth::user()->id;
$comment->comment = $request->comment;
$comment->approved = true;
$comment->post()->associate($post);
$comment->save();
Session::flash('message', "Message posted successfully!");
return Redirect::back();
}
PostsController:
public function delete($id){
DB::table('posts')->where('id',$id)->delete();
return redirect('/profile/' . auth()->user()->id);
}
My view
#foreach($post->comments as $comment)
<div class="comment d-flex ">
<p><strong><a class="text-dark" href="/profile/{{ $comment->user_id }}">{{ $comment->username}}</a>: </strong> {{ $comment->comment}}</p>
#can('update', $post->user->profile)
<div class="dropdown col-md-6">
<button type="button" class="btn btn-primary dropdown-toggle btn-sm" style="background-color: #ffffff00;border: 1px solid #555;color: black;padding: 0 5px" data-toggle="dropdown">
Select
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Edit comment</a>
<a class="dropdown-item" title="Options" style="text-decoration: none;" href="/deleteComment/{{$comment->id}}">Delete comment</a>
</div>
</div>
</div>
#endcan
#endforeach
My route
Route::post('comments/{post_id}', ['uses' => 'CommentsController#store', 'as' => 'comments.store']);
Route::get('/deleteComment/{id}', 'CommentsController#delete');
Try this to restrict the deletion only for the authenticated user who owns the comment:
/**
* Comments Controller Method Delete
*/
public function delete($id){
if(!DB::table('comments')->where('id',$id)->where('user_id',auth()->user()->id)->delete()){
Session::flash('remove', "You do not have permission to delete the comment!");
}else{
Session::flash('remove', "Message removed successfully!");
}
return Redirect::back();
}
For your second question, I think that what happens is that by not having comments you are using the variable without results.
You can try to enclose the statement where you use the variable $comments using this.
For Controller or others files php
if (!$comment->isEmpty()) {
//your code
}
if ($comment->count()) {
//your code
}
if (count($comment)) {
//your code
}
For Blade
#if(!$comment->isEmpty())
//your code
#endif
#if($comment->count())
//your code
#endif
#if(count($comment))
//your code
#endif
I hope I could help you, if not, please attach more code where they appear exactly what he says, since comments and delete the picture, since I have not seen in the code you have attached. Thanks and good luck.
References
$comment->isEmpty
$comment->count() and count($comment)
Updated
<div class="row">
<div class="col-md-12">
#if(!$post->comments->isEmpty()) //****Added
#if($post->comments->count() > 0)
#foreach($post->comments as $comment)
<div class="comment d-flex ">
<p><strong><a class="text-dark"
href="/profile/{{ $comment->user_id }}">{{ $comment->username}}</a>:
</strong> {{ isset($comment->comment) ? $comment->comment : "--" }}</p>
#can('update', $post->user->profile)
<div class="dropdown col-md-6">
<button type="button" class="btn btn-primary dropdown-toggle btn-sm"
style="background-color: #ffffff00;border: 1px solid #555;color: black;padding: 0 5px"
data-toggle="dropdown">
Select
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Edit comment</a>
<a class="dropdown-item" title="Options" style="text-decoration: none;"
href="/deleteComment/{{$comment->id}}">Delete comment</a>
</div>
</div>
</div>
#endcan
#endforeach
#endif
#endif //****Added
</div>
</div>
Updated for delete if admin or no
/**
* Comments Controller Method Delete
*/
public function delete($id)
{
$comment = DB::table('comments')->where('id', $id):
if(!auth()->user()->admin){
$comment->where('user_id', auth()->user()->id);
}
if (!$comment->delete()) {
Session::flash('remove', "You do not have permission to delete the comment!");
} else {
Session::flash('remove', "Message removed successfully!");
}
return Redirect::back();
}
The first question can be done easily. In your destroy() function, just check comment owner:
// Check comment owner
if($comment->user_id != \Auth::id()){
return abort(401);
}
// Do logic code to delete comment.
The second question, you can check exist comment like this :
if(! $comments->isEmpty()) {
// Do logic code to show comment
}
There's 2 buttons on my blade like this :
<a data-url="{{route('trip.out', ['trip' => $trip->id])}}" data-table-name="#dataTable" class="btn btn-lg btn-primary out">Set - Out</a>
<a data-url="{{route('trip.completed', ['trip' => $trip->id])}}" data-table-name="#dataTable" class="btn btn-lg btn-primary completed">Set - Complete</a>
#push('custom_js')
<script type="text/javascript">
$(document).ready(function() {
$('a.out, a.completed').click(function(e) {
$.redirect($(this).data('url'), {
_token : '{{ csrf_token() }}',
}, 'POST');
})
});
</script>
#endpush
the one I want is once I click complete it return finish button, so i put this :
#if ($trip->id == 1)
Finish;
#endif
it doesn't work. Note out = 0, complete = 1. status updated on database but it didn't return finish button.
any idea about the problem?
Problem may be due to this..
href="javascript:;"
SO change it as
#if ($trip->id == 1)
Finish;
#endif
When the html have generated with the laravel php, there is no ralations with the blade code.
The blade if is the server code, have nothing todo with you client button click.
If you want to do that, use client js code.