How to exclude certain styling in page2 in pagination - php

I have followed Jeffery Way in Laravel 8 from scratch amazing series but I'm having a trouble in pagination. In the index page we're making our latest post to have a specific styling and then first 2 posts comes after with a different styling and then rest of posts in different styling. The problem is that these styles are carrying over with us to page2 and 3 and ...etc
I want to make this to only posts in page1 or homepage and when I go to page 2 I should have a default styling for all posts.
This is the index
<x-bloglayout>
#include('posts.__header')
#if ($posts->count())
<x-featuredCard :post="$posts[0]" />
#if ($posts->count() > 1)
<div class="lg:grid lg:grid-cols-2">
<x-postCard :post="$posts[1]" />
<x-postCard :post="$posts[2]" />
</div>
<div class="lg:grid lg:grid-cols-3">
#foreach ($posts->skip(3) as $post)
<x-postCard :post="$post" />
#endforeach
</div>
#endif
{{ $posts->links() }}
#else
<p class="text-center">No posts matches your search, please check back later</p>
#endif
</x-bloglayout>
I tried to use if directive to say if route is home or ?/page1 do this if not do that but it doesn't seem to work.
This is my pagination:
public function index()
{
return view('posts.index', [
'posts' => Post::latest()->filter(request(['search', 'category', 'author']))->paginate(6)->withQueryString(),
]);
}
Thanks

You can use currentPage() method on paginator and check if it's on first page. May not be fanciest way but here is an example:
<x-bloglayout>
#include('posts.__header')
#if ($posts->count())
<x-featuredCard :post="$posts[0]" />
#if ($posts->count() > 1)
#if($posts->currentPage() == 1)
<div class="lg:grid lg:grid-cols-2">
<x-postCard :post="$posts[1]" />
<x-postCard :post="$posts[2]" />
</div>
#endif
<div class="lg:grid lg:grid-cols-3">
#foreach ($posts->skip($posts->currentPage() == 1 ? 3 : 0) as $post)
<x-postCard :post="$post" />
#endforeach
</div>
#endif
{{ $posts->links() }}
#else
<p class="text-center">No posts matches your search, please check back later</p>
#endif
</x-bloglayout>
You can check Paginator methods from Laravel 8.x document: https://laravel.com/docs/8.x/pagination#paginator-instance-methods

Related

Laravel Livewire live search not correctly updating results

I have the following livewire code to perform a search of page titles which works fine on the first search, but subsequent searches do not completely remove the results from the previous search.
namespace App\Http\Livewire\Page;
use App\Models\Page;
use Livewire\Component;
class Search extends Component
{
public $searchQuery = "";
public $searchResults;
public function resetSearchValue() {
$this->searchQuery = "";
}
public function mount() {
$this->reset();
}
public function render()
{
if(strlen($this->searchQuery) > 2) {
$this->searchResults = Page::query()
->select(['title', 'slug'])
->where('title', 'like', "%{$this->searchQuery}%")
->get();
}
return view('livewire.page.search');
}
}
and
<div>
<input
wire:model.debounce.350ms="searchQuery"
#focus="searchFocused = true"
#blur="searchFocused = false"
#click.outside="$wire.resetSearchValue()"
autocomplete="off"
type="text"
placeholder="Search..."
id="sitesearch"
>
#if(strlen($searchQuery) > 0)
<div
role="menu"
aria-orientation="vertical"
-labelledby="menu-button"
tabindex="-1"
>
<div class="py-1" role="none">
#if(strlen($searchQuery) > 2)
#if($searchResults->count() > 0)
#foreach($searchResults as $result)
<a
href="{{ route('pages.index', $result->slug) }}"
role="menuitem"
tabindex="-1"
id="menu-item-0"
>{{ $result->title }}</a>
#endforeach
#else
<p>
No results found
</p>
#endif
#else
<p>
You need to type at least 3 characters
</p>
</div>
</div>
#endif
</div>
Searching for "Page" for example will return something like
My Page 1
Page 2
Wonderful Page 3
But if I then search for "Page Z" the results I get are
My Page 1
Page 2
No results found
If I the search for "Page Zz" the results I get are
My Page 1
No results found
I can't work out why it's not clearing the results from previous results.
Basically, this is the result of a DOM-diffing issue Livewire has when it can't keep track of elements, typically dynamic elements generated in a loop.
The simple solution to this, is to add wire:key with a value to the root element in your loop, like shown below.
#if(strlen($searchQuery) > 2)
#if($searchResults->count() > 0)
#foreach($searchResults as $result)
<a
href="{{ route('pages.index', $result->slug) }}"
role="menuitem"
tabindex="-1"
id="menu-item-0"
wire:key="result-{{ $result->id }}"
>{{ $result->title }}</a>
#endforeach
#else
<p wire:key="no-results">
No results found
</p>
#endif
#else
<p wire:key="searchquery-short">
You need to type at least 3 characters
</p>
#endif
Also, I've added these to the other options which may be shown in place, just so it's no doubt about which element it should show.
Just a note, all the values to wire:key on a page must be unique (like with ID attributes to HTML elements).

Add a block field from a specific article

I have an article, each article has article_blocks, the blocks have a video_link field
And I need to display this field in the list of articles
This is how the article list output is roughly implemented
<div class="blog-list">
#foreach($articles as $article)
<div class="blog-article">
<div class="video-button video-modal-button-blog" data-video="https://www.youtube.com/embed/{{ $article_block->video_link }}">
<span>Watch video</span>
</div>
<h2 class="blog-article__title">{{ $article->title }}</h2>
<span>{{ date('d F Y', strtotime($article->published_at)) }}</span>
<span>{{ $article->getTotalViews() }} Views</span>
</div>
#endforeach
</div>
Each article has a button to open a video, but this video field itself is not in the article itself, but in the article blocks
I now take this field from the block and output it, it turns out like this
<?php
use App\Models\ArticleBlock;
$article_block = ArticleBlock::whereNotNull('video_link')->first();
?>
<div class="blog-list">
#foreach($articles as $article)
<div class="blog-article">
#if ($article_block->video_link !== 'null')
<div class="video-button video-modal-button-blog" data-video="https://www.youtube.com/embed/{{ $article_block->video_link }}">
<span>Watch video</span>
</div>
#endif
<h2 class="blog-article__title">{{ $article->title }}</h2>
<span>{{ date('d F Y', strtotime($article->published_at)) }}</span>
<span>{{ $article->getTotalViews() }} Views</span>
</div>
#endforeach
</div>
As a result, I get this field with video and it is displayed, but the same video is displayed for all articles in the list, and each article should have its own field and its own video. How can this be fixed?
I probably need to look for something like blocks by article id
$article_block = ArticleBlock::where('article_id', $article->id)->whereNotNull('video_link')->first();
But I can't get id
Cant write comment, under 25 rep :(
data-video="https://www.youtube.com/embed/{{ $article_block->video_link }}"
This looks wrong. You should eager load article blocks (eager loading is generally faster than lazy loading) for all articles with a with statement in your eloquent query see: https://laravel.com/docs/8.x/eloquent-relationships#eager-loading
Then if everything is correct you should be able to do just {{ $article->block->video_link }} or something similar.
Above is right if article has only one article block (one to one relationship).
But it seems that article has multiple blocks (one to many relationship) so you would need to iterate over each of the article block as well with another #foreach statement.
#foreach($articles as $article)
#foreach($article->article_blocks as $block)
<p>URL of video is: https://www.youtube.com/embed/{{ $block->video_link }}</p>
#endforeach
#endforeach
Now lets answer your question why video is same everywhere? Because you've coded it as so. You should NEVER write custom queries in your blade files.
Here i am referring to this part of your code:
<?php
use App\Models\ArticleBlock;
$article_block = ArticleBlock::whereNotNull('video_link')->first();
?>
Queries should be either in controllers/services or repositories.
$article_block = ArticleBlock::whereNotNull('video_link')->first();
will just give you first article block defined in ur database where video_link is not null. It won't guarantee that ArticleBlock belongs to given Article.
Lets hope that i put you on the right path ^.^

Pagination Link

What is the correct way to call the "Links" function after this "Foreach"?
I don't know how to handle the variable to put in function.
#inject('usuarios', 'App\User')
#foreach($usuarios->getIndicados() as $user)
#endforeach
<div class="row">
<div class="col-12 text-center">
{{ $usuarios->getIndicados()->links() }}
</div>
</div>
Maybe it's just an editing error, but in your output the -tags don't seem to be closed again. Also, there should be no space like < a> at the beginning of the tag. And < a hr_ef= ... is obviously wrong.
In order to style them, you can add a class attribute to the tags while building the string and do the style-stuff in css.
This is what laravel document provides. You need to add links in the collection.
<div class="container">
#foreach ($users as $user)
{{ $user->name }}
#endforeach
{{ $users->links() }}

Included blade template repeating in each foreach loop iteration

I'm using Blade templating with Laravel and I'm trying to use a #foreach loop to display notifications. The problem is that if I have say 10 notifications, the first notification is repeated 10 times.
The code to output each notification:
#foreach ( Auth::user()->unreadNotifications as $notification )
{{ $notification->type->web_template }}
{{ $notification->id }}
#include($notification->type->web_template)
#endforeach
web_template will output a path to the template: notifications.web.user_alert
For each iteration of the loop the {{ $notification->type->web_template }} and {{ $notification->id }} will output what they're supposed to but #include($notification->type->web_template) will only output the first notification each time.
So the output will look like:
156 notification.web.new_message
You have a new message from Joe.
154 notification.web.user_alert
You have a new message from Joe.
145 notification.web.new_like
You have a new message from Joe.
I think it's some sort of cache issue maybe, but I couldn't find anyone with the same problem.
Any ideas?
UPDATE: Adding some code
Example notification view:
#extends('layouts.notification-wrapper')
#section('url', url('jobs/'.$notification->job_id.'#highlight'.$notification->bid_id))
#section('image', '/assets/img/no-photo.jpg')
#section('header', $notification->collector->firstname . ' ' . $notification->collector->secondname)
#section('description')
has placed a bid of €{{ number_format($notification->bid()->withTrashed()->first()->amount,0) }} on your job.
#stop
Notification wrapper:
<li #if(!$notification->read)
class="unread"
#endif>
<a href="#yield('url')" data-id="{{ $notification->id }}">
<div class="pull-left">
<img src="#yield('image')" class="img-circle" alt="user image">
</div>
<h4>
#yield('header')
<small><i class="fa fa-clock-o"></i> {{ $notification->created_at->diffForHumans()}}</small>
</h4>
<p> #yield('description')</p>
</a>
</li>
Answering my own question!
Found this: Laravel Blade Templates Section Repeated / cache error
Basically whatever way it works I need to overwrite my sections when looping and using #yield... I think. So I need to replace #stop with #overwrite in my views.

How to display one picture in this ad? Laravel 4

I have problem with displayin one picture in my home page.
Currently, I loaded some photos. I created a column in the database 'thumbnail'. Wants to do so, to load the photo - thumbnail where the column 'thumbnail
have record = 1.
My Homecontroller:
public function getHome(){
return View::make('pages.home')
->with('offers', Offer::take(8)->orderBy('created_at', 'DESC')->get());
}
my view:
#foreach($offers as $offer)
<div class="col-sm-3" style="border: 1px solid #AADFFF; height:350px; ">
#foreach($offer->photosofoffers as $photosofoffer)
<a href="{{ route('pages.view', $offer->id) }}">
<!--<a href="/pages/view/{{ $offer->id }}">-->
{{ HTML::image($photosofoffer->file, $photosofoffer->title, array( 'class'=>'feature', 'width'=>'240', 'height'=>'127')) }}
</a>
#endforeach
<h3><a href="{{ route('pages.view', $offer->id) }}">{{ $offer->title }}</h3>
<p> {{ $offer->description }} </p>
<h5>Availability: <span class="{{ Availability::displayClass($offer->availability) }}">
{{ Availability::display($offer->availability) }}
</span>
</h5>
<p>Cena <span>{{ $offer->price }}</span>
</p>
#endforeach
Where should I add something?
At the moment loads all the images of the announcement. He wants to load one image, where the 'thumbnail' = 1.
You can eager load the relations and apply a constraint. Something like:
Offer::with(array('photosofoffers' => function($q) {
$q->where('thumbnail', 1)->take(1);
}))->take(8)->orderBy('created_at', 'DESC')->get();
http://laravel.com/docs/5.0/eloquent
If you want to load only those offers that have a photo/thumbnail
Offer::with('photosoffers')->whereHas('photosofoffers', function($q) {
$q->where('thumbnail', 1)->take(1);
})->take(8)->orderBy('created_at', 'DESC')->get();

Categories