أمير عبد الكريم نشر 2 أبريل أرسل تقرير نشر 2 أبريل لدي هذا المكون: <?php namespace App\Livewire; use Livewire\Component; use App\Models\Post; class PostsList extends Component { protected $listeners = ['toggleFollow' => '$refresh']; public function getPostsProperty() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); return Post::whereIn('user_id', $ids)->latest()->get(); } public function render() { return view('livewire.posts-list'); } } ولدي posts-list.blade.php <div class="w-[30rem] mx-auto lg:w-[95rem]"> @forelse($this->posts as $post) <livewire:post :post="$post" :wire:key="'post_'.$post->id"/> @empty <div class="max-w-2xl gap-8 mx-auto dark:text-gray-100"> {{__('Start Following Your Friends and Enjoy.')}} </div> @endforelse </div> كيف اقوم بإضافة ميزة التحميل التلقائي للمنشورات؟ حاولت بحث ع يوتيوب ولكن ما استفدت ولا شيء. 1 اقتباس
1 محمد عاطف17 نشر 2 أبريل أرسل تقرير نشر 2 أبريل الامر بسيط ويوجد عدة طرق ولكن الافضل هو . اولا انشاء متغير يحمل المنشورات التى تم تحميلها الى الان حيث لا نريد فى كل مرة يصل المستخدم الى اخر الصفحة وناتى بالمنشروات من جديد , ونعطى قيمة افتراضية لهذا المتغير بمصفوفة فارغة . public $postCotainer = []; وايضا نقوم بانشاء متغيرين اخرين احدهما يحمل القيمة الافتراضية لعدد المنشورات التى سيتم تحميلها فى بداية الصفحة او حتى عند التمرير لاسفل الصفحة . والاخر يحمل عدد المنشورات الذى تم عرضها الى الان . public $take = 5; public $skip = 0; والان نقوم بانشاء استماع الى حدث التمرير جديد وفى الدالة نقوم بزيادة عدد المنشورات التى عرضها . protected $listeners = ['scrollPosts'=>'getMorePosts']; public function getMorePosts() { $this->skip += $this->take; } هكذا كل مرة يتم التمرير لاسفل الصفحة نقوم بزيادة العدد الذى تم عرضه . والان فى الدالة getPostsProperty نضع هذا الكود. public function getPostsProperty() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); $this->postCotainer = array_merge($this->postCotainer,Post::whereIn('user_id', $ids)->latest()->skip($this->skip)->take($this->take)->get()->all()); return $this->postCotainer; } لاحظ هنا اننا اولا استخدمنا دالة array_merge وذلك لدمج المنشورات التى تم تحميلها سابقا الى المنشورات الجديدة الذى سوف يتم تحميلها . ولاحظ اننا فى الاستعلام الخاص بال sql اضفنا داليتن الاولى هى skip اى اننا لا نريد ان ناتى بعدد معين بالمنشورات وهى المنشورات التى تم تحميلها بالفعل ولذلك نمرر لها المتغير skip الذى يحمل عدد المنشروات الذى تم تحميلها الى الان. والدالة take التى تسمح لنا باحضار عدد معين فقط من المنشورات ولذلك ارسلنا لها المتغير take الذى يحمل عدد المنشورات التى نريد عرضها . وبهذا نكون قد انتهينا من الكود الخلفى . ولكن ستجد مشكلة سوف تحدث فى الحدث الذى لديك toggleFollow فمثلا اذا قام المستخدم بالغاء متابعه او متابعه مستخدم جديد فان منشوراته التى تم تحميلها سابقا نريد ان نحذفها او عرضها . لذلك سنجعل عند استماع الى الحدث toggleFollow هو حذف جميع المنشورات التى تم تحميلها سابقا واعادة التحميل من جديد حتى لا تحدث تلك المشكلة.وهذا هو كود المكون كاملا بعد التعديل. <?php namespace App\Livewire; use Livewire\Component; use App\Models\Post; class PostsList extends Component { protected $listeners = ['toggleFollow' => 'resetPosts','scrollPosts'=>'getMorePosts']; public $take = 5; public $skip = 0; public $postCotainer = []; public function resetPosts() { $this->postCotainer = []; $this->take = 5; $this->skip = 0; } public function getPostsProperty() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); $this->postCotainer = array_merge($this->postCotainer,Post::whereIn('user_id', $ids)->latest()->skip($this->skip)->take($this->take)->get()->all()); return $this->postCotainer; } public function getMorePosts() { $this->skip += $this->take; } public function render() { return view('livewire.posts-list'); } } اما فى الواجهة الامامية فسوف نضيف استماع الى حدث التمرير و التحقق من ان المستخدم قد قام بالتمرير الى اخر الصفحة . واذا كان قام بالتمرير الى اخر الصفحة نقوم بارسال الحدث scrollPosts الذى سوف يقوم باحضار المزيد من المنشورات وبذلك كلما قام بالتمرير ياتى بالمنشورات الجديد . <div class="w-[30rem] mx-auto lg:w-[95rem]"> @forelse($this->posts as $post) <livewire:post :post="$post" :wire:key="'post_'.$post->id" /> @empty <div class="max-w-2xl gap-8 mx-auto dark:text-gray-100"> {{ __('Start Following Your Friends and Enjoy.') }} </div> @endforelse </div> @script <script> window.onscroll = function(ev) { if ((window.innerHeight + Math.round(window.scrollY)) >= document.body.offsetHeight) { $wire.dispatch('scrollPosts'); } }; </script> @endscript وهكذا قد انتهينا من جميع الاكود ويمكنك استعمالها وستعمل معك . ويمكنك تغير القيمة الافتراضية للمتغير take على حسب عدد المنشورات التى تريدها حيث انا اعطيته قيمة ابتدائية ب 5 1 اقتباس
0 أمير عبد الكريم نشر 2 أبريل الكاتب أرسل تقرير نشر 2 أبريل بتاريخ 9 ساعة قال محمد_عاطف: الامر بسيط ويوجد عدة طرق ولكن الافضل هو . اولا انشاء متغير يحمل المنشورات التى تم تحميلها الى الان حيث لا نريد فى كل مرة يصل المستخدم الى اخر الصفحة وناتى بالمنشروات من جديد , ونعطى قيمة افتراضية لهذا المتغير بمصفوفة فارغة . public $postCotainer = []; وايضا نقوم بانشاء متغيرين اخرين احدهما يحمل القيمة الافتراضية لعدد المنشورات التى سيتم تحميلها فى بداية الصفحة او حتى عند التمرير لاسفل الصفحة . والاخر يحمل عدد المنشورات الذى تم عرضها الى الان . public $take = 5; public $skip = 0; والان نقوم بانشاء استماع الى حدث التمرير جديد وفى الدالة نقوم بزيادة عدد المنشورات التى عرضها . protected $listeners = ['scrollPosts'=>'getMorePosts']; public function getMorePosts() { $this->skip += $this->take; } هكذا كل مرة يتم التمرير لاسفل الصفحة نقوم بزيادة العدد الذى تم عرضه . والان فى الدالة getPostsProperty نضع هذا الكود. public function getPostsProperty() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); $this->postCotainer = array_merge($this->postCotainer,Post::whereIn('user_id', $ids)->latest()->skip($this->skip)->take($this->take)->get()->all()); return $this->postCotainer; } لاحظ هنا اننا اولا استخدمنا دالة array_merge وذلك لدمج المنشورات التى تم تحميلها سابقا الى المنشورات الجديدة الذى سوف يتم تحميلها . ولاحظ اننا فى الاستعلام الخاص بال sql اضفنا داليتن الاولى هى skip اى اننا لا نريد ان ناتى بعدد معين بالمنشورات وهى المنشورات التى تم تحميلها بالفعل ولذلك نمرر لها المتغير skip الذى يحمل عدد المنشروات الذى تم تحميلها الى الان. والدالة take التى تسمح لنا باحضار عدد معين فقط من المنشورات ولذلك ارسلنا لها المتغير take الذى يحمل عدد المنشورات التى نريد عرضها . وبهذا نكون قد انتهينا من الكود الخلفى . ولكن ستجد مشكلة سوف تحدث فى الحدث الذى لديك toggleFollow فمثلا اذا قام المستخدم بالغاء متابعه او متابعه مستخدم جديد فان منشوراته التى تم تحميلها سابقا نريد ان نحذفها او عرضها . لذلك سنجعل عند استماع الى الحدث toggleFollow هو حذف جميع المنشورات التى تم تحميلها سابقا واعادة التحميل من جديد حتى لا تحدث تلك المشكلة.وهذا هو كود المكون كاملا بعد التعديل. <?php namespace App\Livewire; use Livewire\Component; use App\Models\Post; class PostsList extends Component { protected $listeners = ['toggleFollow' => 'resetPosts','scrollPosts'=>'getMorePosts']; public $take = 5; public $skip = 0; public $postCotainer = []; public function resetPosts() { $this->postCotainer = []; $this->take = 5; $this->skip = 0; } public function getPostsProperty() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); $this->postCotainer = array_merge($this->postCotainer,Post::whereIn('user_id', $ids)->latest()->skip($this->skip)->take($this->take)->get()->all()); return $this->postCotainer; } public function getMorePosts() { $this->skip += $this->take; } public function render() { return view('livewire.posts-list'); } } اما فى الواجهة الامامية فسوف نضيف استماع الى حدث التمرير و التحقق من ان المستخدم قد قام بالتمرير الى اخر الصفحة . واذا كان قام بالتمرير الى اخر الصفحة نقوم بارسال الحدث scrollPosts الذى سوف يقوم باحضار المزيد من المنشورات وبذلك كلما قام بالتمرير ياتى بالمنشورات الجديد . <div class="w-[30rem] mx-auto lg:w-[95rem]"> @forelse($this->posts as $post) <livewire:post :post="$post" :wire:key="'post_'.$post->id" /> @empty <div class="max-w-2xl gap-8 mx-auto dark:text-gray-100"> {{ __('Start Following Your Friends and Enjoy.') }} </div> @endforelse </div> @script <script> window.onscroll = function(ev) { if ((window.innerHeight + Math.round(window.scrollY)) >= document.body.offsetHeight) { $wire.dispatch('scrollPosts'); } }; </script> @endscript وهكذا قد انتهينا من جميع الاكود ويمكنك استعمالها وستعمل معك . ويمكنك تغير القيمة الافتراضية للمتغير take على حسب عدد المنشورات التى تريدها حيث انا اعطيته قيمة ابتدائية ب 5 ماشاء الله شكراً لك كثيراً الأمر طلع سهل وانا طورت الكود بحيث يقوم بإزالة اول منشور اذا كان عدد المنشورات اكثر من 10 لضمان تجربة افضل. public function getMorePosts() { $this->skip += $this->take; if (count($this->postContainer) > 10) { array_shift($this->postContainer); } } ولاحظت انك استخدم التابع all() لضمان إسترجاع الإستعلام كمصفوفة. وليس كـ اوبجكت اليس كذلك؟ ولكن الموجه @script هو جديد بالنسبة ليا كنت اظنه @push('scripts') شكراً لك مرة اخرى. 1 اقتباس
0 سمير عبود نشر 3 أبريل أرسل تقرير نشر 3 أبريل بإمكانك إستخدام نظام الصفحات (pagination) المتاح في Laravel مع Intersection Observer API لتحقيق ذلك. سنقوم بإنشاء خاصية page للدلالة على الصفحة الحالية ترتفع قيمتها بـ 1 مع كل جلب لمجموعة بيانات جديدة سنقوم بإنشاء خاصية حاوية (كما شرح المدرب محمد في الأعلى) الهدف منها تخزين السجلات use Illuminate\Support\Collection; public int $page = 1; public Collection $posts; سنقوم بإنشاء خاصية من النوع computed في Livewire لإنشاء paginator يقوم بجلب مجموعة السجلات الخاصة بالصفحة الحالية: use Livewire\Attributes\Computed; #[Computed] public function paginator() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); return Post::whereIn('user_id', $ids) ->latest() ->paginate(10, ['*'], 'page', $this->page); } أعلاه يتم جلب 10 سجلات في كل مرة، يمكنك التحكم في ذلك من خلال الوسيط الأول للتابع paginate سنُنشئ تابع مسؤول عن تحميل المزيد لإضافة سجلات الصفحة الحالية إلى الحاوية الأساسية ورفع قيمة page: public function loadMore(): void { $this->posts->push( ...$this->paginator->getCollection() ); $this->page = $this->page + 1; } ثم في التابع mount نقوم بتهيئة الحاوية وإستدعاء التابع loadMore لجلب سجلات أول صفحة: public function mount(): void { $this->posts = collect(); $this->loadMore(); } ليُصبح المكون ككل بالشكل التالي: <?php namespace App\Livewire; use Livewire\Component; use App\Models\Post; use Illuminate\Support\Collection; use Livewire\Attributes\Computed; class PostsList extends Component { protected $listeners = ['toggleFollow' => '$refresh']; public int $page = 1; public Collection $posts; public function mount(): void { $this->posts = collect(); $this->loadMore(); } public function loadMore(): void { $this->posts->push( ...$this->paginator->getCollection() ); $this->page = $this->page + 1; } #[Computed] public function paginator() { $ids = auth()->user()->following()->wherePivot('confirmed', true)->get()->pluck('id'); return Post::whereIn('user_id', $ids) ->latest() ->paginate(10, ['*'], 'page', $this->page); } public function render() { return view('livewire.posts-list'); } } الآن ستحتاج فقط إلى إستخدام الموجه x-intersect المتاح في إطار العمل alpine.js لإستدعاء التابع loadMore من المكون، لست بحاجة إلى تثبيت الإطار فـ Livewire الإصدار الثالث يتيح إستعمال alpine.js دون حاجة لتثبيته: @if ($this->paginator->hasMorePages()) <div x-intersect="$wire.loadMore" class="h-12 -translate-y-44"></div> @endif المتصفحات القديمة لا تدعم Intersection Observer API يمكنك إضافة زر لتحميل المزيد يظهر في هذه الحالة: @if ($this->paginator->hasMorePages()) <button wire:click="loadMore">Load more</button> @endif ملف العرض سيكون بالشكل التالي: <div class="w-[30rem] mx-auto lg:w-[95rem]"> @if($posts->count() > 0) @foreach($posts as $post) <livewire:post :post="$post" :wire:key="'post_'.$post->id"/> @endforeach @if ($this->paginator->hasMorePages()) <div x-intersect="$wire.loadMore" class="h-12 -translate-y-44"></div> @endif @if ($this->paginator->hasMorePages()) <button wire:click="loadMore">Load more</button> @endif @else <div class="max-w-2xl gap-8 mx-auto dark:text-gray-100"> {{__('Start Following Your Friends and Enjoy.')}} </div> @endif </div> 1 اقتباس
0 محمد عاطف17 نشر 3 أبريل أرسل تقرير نشر 3 أبريل بتاريخ 11 ساعة قال أمير عبد الكريم: ولاحظت انك استخدم التابع all() لضمان إسترجاع الإستعلام كمصفوفة. وليس كـ اوبجكت اليس كذلك؟ نعم صحيح استخدمت all للحصول على النتيجة كمصفوفة حتى استطيع دمجها مع المنشورات السابقة . بتاريخ 12 ساعة قال أمير عبد الكريم: لكن الموجه @script هو جديد بالنسبة ليا كنت اظنه @push('scripts') نعم الموجه push('scripts')@ هو خاص بالاصدار 2 من مكتبة livewire وبما انك تستعمل الاصدار 3 منها فهم قد قامو بتحديث اسم الموجه ليصبح script@ . ولا شكر على واجب اخى أمير . وبالتوفيق لك ان شاء الله 1 اقتباس
السؤال
أمير عبد الكريم
لدي هذا المكون:
ولدي posts-list.blade.php
كيف اقوم بإضافة ميزة التحميل التلقائي للمنشورات؟ حاولت بحث ع يوتيوب ولكن ما استفدت ولا شيء.
4 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.