I have two tables , categories and product.Each category has id and name. Each product has id, name and category id. Now I want to load the data on each tab when a user click on specific category_id.so related product will be shown on each category tab. I have tried but couldn't get the solution.
Category Model:
class Category extends Model
{
public function products()
{
return $this->hasMany('App\Product');
}
}
Product Model:
class Product extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
Here is my controllers:
public function gettestItem() {
$categories = Category::with('products')->get();
return view('products', compact('categories'));
}
Here is the view :
<div class="container">
<div id="content">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
#foreach ($categories as $category)
<li><a href="#{{$category->id}}" data-toggle="tab" >{{$category->name}}</a></li>
#endforeach
</ul>
<div id="my-tab-content" class="tab-content">
#foreach($categories as $category)
#foreach($category->products as $product)
<div class="tab-pane " id="{{$category->id}}">
{{$product->name}}
</div>
#endforeach
#endforeach
</div>
</div>
</div>
Here is the route:
Route::get('/testItem',[
'uses'=>'ItemController#gettestItem',
'as'=>'testItem'
]);
if anyone could help me solve the problem will be appreciated.
If you have defined your schema and relations properly then function should be as:
public function gettestItem() {
$categories = Category::with('products')->get();
return view('products', compact('categories'));
}
then you can access product of each category as:
foreach ($categories as $category) {
$category->product; // gives all products corresponding to $category
}
And also please read the Docs
Update
Your 2nd foreach should be as:
<div id="my-tab-content" class="tab-content">
#foreach($categories as $category)
<div class="tab-pane" id="{{$category->id}}">
#foreach($category->products as $product)
<div>
{{$product->name}}
</div>
#endforeach
</div>
#endforeach
</div>
You can also use following code to get only those categories which have corresponding products:
$categories = Category::has('products')->with('products')->get();
Related
In general, I need to make a pop-up menu with a choice of a category, everything works for me, but there is one point that needs to be improved.
When the category has already been selected, it is necessary that in the blog-filter class, All should be changed to the selected category, I tried many options, but all the non-working ones turned out to be.
html
<div class="blog-filter">
<div class="blog-filter_item active js-filter-blog-list" data-filter="all">All</div>
</div>
<div class="blog-filter-container">
<div class="container">
<h1 class="blog-filter-title">Choose Category</h1>
<div class="item-wrapper">
<div class="blog-filter_item active" data-filter="all">All</div>
#foreach($categories as $category)
<div class="blog-filter_item" data-filter=".category_{{$category->id}}">{{ $category->title }} ({{ $category->articles_count }})</div>
#endforeach
</div>
</div>
</div>
#foreach ($articles as $article)
<div class="blog-list category_{{ $article->blog_category_id }}">
<div class="article article--left" >
<h2 class="article_title">{{ $article->title }}</h2>
</div>
<div class="article article--right">
<h2 class="article_title">{{ $article->title }}</h2>
</div>
</div>
#endforeach
js
$('.js-filter-blog-list').on('click', event => {
const modalFilter = document.querySelector('.blog-filter-container');
$(modalFilter).toggleClass('open');
});
document.querySelectorAll('.blog-filter_item').forEach(el => {
el.addEventListener('click', () => {
document
.querySelector('.blog-filter_item.active')
.classList.remove('active');
el.classList.add('active');
var dataFilter = $(el).attr('data-filter');
if (dataFilter == 'all') {
$('.blog-list').show();
}
else {
$('.blog-list').hide();
$(dataFilter).show();
}
});
});
Solution:
#foreach($categories as $category)
<div class="blog-filter_item" data-filter=".category_{{$category->id}}" value="{{ $category->title }} ({{ $category->articles_count }})>{{ $category->title }} ({{ $category->articles_count }})</div>
#endforeach
var dataFilter = $(el).attr('data-filter');
var value = $(el).attr('value');
if (dataFilter == 'all') {
$('.blog-list').show();
$('.js-filter-blog-list').text('All');
}
else {
$('.blog-list').hide();
$(dataFilter).show();
$('.js-filter-blog-list').text(value);
}
I am still very weak in Ajax, but they told me that this is a way out of the situation that I have developed.
I have a javascript function that filters categories. There is also alternation of lists in php.blade.
When I click on "All", all blogs are displayed and the alternation is working properly. When I select the "desired category", all blogs from this category are displayed, but alternation does not work.
I was prompted that you can is to call one ajax functional on category selection and return the HTML response on that ajax call. But I don't know how to do this, can anyone help?
JavaScript
$('.category-filter_item').click(function(){
$('.category-filter_item').removeClass('active')
$(this).addClass('active')
var dataFilter = $(this).attr('data-filter');
$('.blog-list').hide()
$(dataFilter).show()
})
php.blade
#extends('layouts.app')
#section('content')
<div class="container">
<div class="category-filter" id="filter">
<div class="category-filter_item active" data-filter="*">All</div>
#foreach($categories as $category)
<div class="category-filter_item" data-filter=".category_{{$category->id}}">{{ $category->title }}</div>
#endforeach
</div>
#foreach ($blogs as $index => $blog)
<div class="blog-list">
#if ($index % 2 === 1) //Alternation
<div class="blog blog--left" >
<h2 class="blog_title">{{ $blog->title }}</h2>
</div>
#else
<div class="blog blog--right">
<h2 class="blog_title">{{ $blog->title }}</h2>
</div>
#endif
</div>
#endforeach
</div>
#endsection
Controller
public function index()
{
$blogs = Blog::all();
$categories = Category:all();
return view('blog', compact('blogs', 'categories'));
}
Need to create new route and controller function to return only the selected category blogs and that should be in json format
Once that is done need to use the ajax call to the above route in the click function defined. Capture the response and then iterate and generate the html that should be inside the blog-list in your script. then update the html inside blog-list value.
refer this link
refer this for making ajax call link
so I have a code that shows all my product
#foreach($products as $product)
<div class="col-lg-4 col-md-4 col-sm-6 col-12 event-item-col ">
<div class="card card-event info-overlay">
<div class="img has-background h-50">
<div class="pop-info ">
<span class="event-badges ">
<span class="badge price-tag big badge-default">{{$product->price}}</span>
</span>
</div>
<a href="/product/{{$product->id}}" class="event-pop-link">
<span class="event-badges ">
<span class="badge badge-danger"> if he buy</span>
</span>
<div class="event-pop-info">
<p class="badge">{{$product->price}}</p>
<p class="publisher">by <strong><?php $id = $product->user_id; $users = $user->findOrFail($id); echo $users->first; ?> <?php echo $user->last ?></strong></p>
</div>
</a>
<a href="event-details.html">
<img alt="340x230" class="card-img-top img-responsive h-100" data-holder-rendered="true" src="image/products/product{{$product->id}}.jpg"> </a>
</div>
<div class="card-body h-50">
<h4 class="card-title">
{{$product->pname}}
</h4>
<p class="card-tex" style="overflow: hidden">{{$product->smalldescription}}</p>
<div class="card-event-info">
<p class="event-location"><i class="fas fa-location-arrow"></i>
<a class="location" href="/user/product/{{$id}}"><?php echo $users->first; ?> <?php echo $user->last ?></a></p>
<p class="event-time"><i class="fas fa-calendar-alt"> {{$product->created_at->format('m/d/Y')}}</i></p>
</div>
</div>
</div>
</div>
#endforeach
and this is my controller
public function index()
{
$user = User::find(1);
$products = product::orderBy('created_at', 'desc')->Paginate($perPage = 15, $columns = ['*'], $pageName = 'page', $page = null);
return view('welcome', compact('products', 'user'));
}
like you can see in my view I have this code
<?php $id = $product->user_id; $users = $user->findOrFail($id); echo $users->first; ?> <?php echo $user->last ?>
that makes me able to get the name of the user that create this product, product and user table has one too many relations.i want to change this code to a better and smaller code.
product->user->first
don't work.
I tried it so many ways but that just doesn't work.
if anyone can help me to get data with laravel way I will be grateful. (sry if my question is duplicate, I tried so many ways but didn't work )
to give u guys more info this is my class
class User extends Authenticatable
{
use Notifiable;
use Friendable;
protected $fillable = [
'first','last', 'email', 'password','phone','question','answer','description',
];
protected $hidden = [
'password', 'remember_token',
];
public function products()
{
return $this->hasMany(Product::class);
}
}
and product class :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
the class product extends Model
{
protected $fillable = [
'part_id', 'smalldescription', 'description', 'pname', 'link', 'price',
];
public function users()
{
return $this->belongsTo(User::class);
}
}
Firstly I would like to point you out that you have already defined the relation in your product model you could use that to access the related user by calling the function. I would also like to suggest you to change the function name in your product model from users to user as belongsTo returns only single instance of the related model.
public function user()
{
return $this->belongsTo(User::class);
}
Coming back to your query when querying products use with load a relation like in your case it would be.
product::with('user')->orderBy('created_at', 'desc')->Paginate($perPage = 15, $columns = ['*'], $pageName = 'page', $page = null);
Then inside your foreach loop on blade get user's name calling user function on $product like:
$product->user->name
I would also suggest to go through the laravel documentation about eloquent relations again.
Querying a relation
Below is the standard page in HTML with pagination working well. The problem arises when I perform a search. I would like to know why when I run the search it complains that "vehicles is an undefined variable"
#foreach($all as $one)
<div class="card-description">
<div class="card-text">
<div class="card-text-wrapper">
<div class="card-details">
<p class="vehicle-name">{{$one->make}}</p>
<p class="vehicle-details">{{$one->year}}</p>
<p class="vehicle-details">{{$one->type}}</p>
</div>
</div>
</div>
<div class="card-text">
<div class="card-text-wrapper">
<h1 class="price-tag">ยข {{$one->price}}</h1>
</div>
</div>
</div>
{{$all->links()}}
#endforeach
Below is the javascript function I tried for performing the search but unfortunately I do not know how to update the pagination to accept the new search values:
function searchVehicle(){
var make = document.getElementById("vehicle_make");
var strMake = make.options[make.selectedIndex].text;
var model = document.getElementById("vehicle_model");
var strModel = model.options[model.selectedIndex].text;
var cardDisplay = document.getElementById("card_display");
var cardDeck = document.getElementById("card_deck");
var strUrl = vehicle_url + strMake + '/' +strModel;
var obj = sendRequest(strUrl);
while (cardDeck.firstChild) {
cardDeck.removeChild(cardDeck.firstChild);
}
}
Below is my form which would be performing the search
{{ Form::open(['route' => 'search','method' => 'GET']) }}
<div>
<div class="wrapper-dropdown-5" tabindex="1" >
<span class="placeholder">Select make</span>
<ul class="dropdown" style="z-index:1000" name="mak" id="vehicle_make">
#foreach($vehicles as $vehicle)
{{--{{$vehicle->id}}--}}
<li class="option-make" id="make" value="{{$vehicle->make}}"><a>{{$vehicle->make}}</a></li>
#endforeach
</ul>
</div>
<div id="dd" class="wrapper-dropdown-5 inactive" tabindex="2" >
<span class="placeholder">Select model</span>
<ul class="dropdown" id="vehicle_model">
</ul>
</div>
</div>
</div>
<div class="button-wrap">
{{Form::submit('Search', ['class' => 'submit-button'])}}
</div>
{{ Form::close() }}
Below is the way I tried to display the search results but had an error that "vehicles" is an undefined variable:
public function searchVehicle(SearchVehicleRequest $request){
$make=$request->input('make');
$model=$request->input('model');
$results = Vehicles::where('make', 'LIKE', '%'.$make. '%')->orWhere('model','LIKE', '%'.$vehicle_model.'%')->paginate(2);
return Response::json(\View::make('Garages.home', array('all' => $results))->render());
}
And my route:
Route::get('search', ['as' => 'search', 'uses' => 'VehiclesController#searchVehicle']);
I can populate the HTML but don't know how to update the pagination..unless this whole process is wrong and there is a simpler way to get this done with ajax? or is page rendering the wrong way to go for something like this??
I want to implement a simple pagination using Handlebars. I am using bootstrap 3. This is what I have:
HTML
<div class = "categories-block">
{{#each category}}
<div class = "category">
<div class = "item">
<h2>{{itemname}}</h2>
View Category
<p class = "item-desc">{{itemndesc}}</p>
</div>
</div>
{{/each}}
</div>
<div class="pagination">
<li>Previous</li>
<li>1</li>
<li>Next</li>
</div>
MODEL
var categorymodel = Backbone.Model.extend({
url: "http://localhost/category.json",
defaults: {
}
});
Right now, everything I get from my model is displayed there. How can I paginate, display 5 items in one page.
Thanks in advance