I am creating a blog in Laravel. I have two tables - posts and categories.
When i want to edit one post, i have a problem with categories. My post controller is sending categories to the view, i can see them while editing, but i don't know how to set the current category in the select option.
The tables are conected:
public function posts(){
return $this->hasMany('App\Post');
}
public function category(){
return $this->belongsTo('App\Category');
}
Controller:
public function edit(Post $post)
{
$categories = Category::all();
return view('admin.posts.edit', compact('post'))->withCategories($categories);
}
View:
<form action="{{ route('posts.update', ["post" => $post->id]) }}" method="post" enctype="multipart/form-data" class="form-horizontal">
#csrf
<div class="form-body">
<div class="form-group">
<label class="col-md-3 control-label">Naslov</label>
<div class="col-md-4">
<input type="text" name='title' value='{{ old("title", $post->title) }}' class="form-control">
#if($errors->has('title'))
<div class='text text-danger'>
{{ $errors->first('title') }}
</div>
#endif
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Kategorija</label>
<div class="col-md-4">
<select class="form-control" name="category_id">
#if(count($categories) > 0)
#foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
#endif
</select>
#if($errors->has('category_id'))
<div class='text text-danger'>
{{ $errors->first('category_id') }}
</div>
#endif
</div>
</div>
How can i make the category display the current category of the selected post in the option select like i have for title? value='{{ old("title", $post->title) }}'
To show the currently associated Category, you can set a default "selected" option based on the $post->category_id:
<option value="{{ $category->id }}" {{ old('category_id', $post->category_id) == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
This a simple ternary that sets the selected attribute of one of the options based on the old() value, or, if old() is not set, then based on the value of $post->category_id
What you are looking for is the selected property of the <option> element.
#forelse ($categories as $category)
<option value="{{ $category->id }}" {{ $category->id == old('category_id', $post->category_id) ? 'selected' : '' }}>
{{ $category->name }}
</option>
#endforelse
A minor change as well in the in you blade template to make use of the #forelse directive for less code.
You could also change your controller code a bit:
return view('admin.posts.edit', compact('post', 'categories'));
Further the laravelcollective/html package might help you a lot in creating forms.
Related
i have two divs (inputbarang and inputkategori). I want to make one of the divs disappear when there's no data in it. For example, when the $produk's value is not null, the inputbarang's div will appear, and the inputkategori's div will be hidden. Whereas, if $produk is empty, then the inputbarang's div will be hidden and the inputkategori's div will appear. I try like this. When $produk is null, the inputbarang's div still appears and the inputkategori's div doesn't appear
Blade.php:
#if($produk !== null)
<div class="form-group row " id="inputbarang" >
<label class="col-form-label col-lg-3 col-sm-12">Barang</label>
<div class="col-lg-4 col-md-9 col-sm-12">
<select class="form-control m-select2" width="500px" id="kt_select2_1" name="id_product[]" multiple="multiple">
#foreach($productall as $p)
#if(in_array($p->id, $productbyIds))
<option value="{{ $p->id }}" selected="true">{{ $p->product }}</option>
#else
<option value="{{ $p->id }}">{{ $p->product }}</option>
#endif
#endforeach
</select>
</div>
</div>
#else
<div class="form-group row" id="inputkategori" >
<label class="col-form-label col-lg-3 col-sm-12">Kategori</label>
<div class="col-lg-9 col-md-9 col-sm-12">
<select class="form-control m-select2" width="500px" id="kt_select2_3" name="id_kategori[]" multiple="multiple">
#foreach($kategoriall as $k)
#if(in_array($k->id, $kategoribyIds))
<option value="{{ $k->id }}" selected="true">{{ $k->kategori }}</option>
#else
<option value="{{ $k->id }}">{{ $k->kategori }}</option>
#endif
#endforeach
</select>
</div>
</div>
#endif
Controller:
$produk = Produk::where('m_product.delete', 0)
->join('tb_promo_detail', 'tb_promo_detail.id_product','=','m_product.id')
->select('m_product.id', 'm_product.product')
->where('tb_promo_detail.id_promo',$id)
->get();
Please correct me if its wrong.. Thank you so much!
Since you are sending a collection to your blade from controller you will need to check if that collection is empty or not. Just checking if it is null or empty array will not give you the right conditional effect.
So use:
#if($produk->first())
or you can also use
#if(!$produk->isEmpty())
I am trying to create a multiple filter function to filter my table. I have a model called Product and it has collections named categories, colors and sizes. I have the following in my view:
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Categories') }}</label>
<select class="form-control" id="select-categories">
<option value="0">All</option>
#foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Colors') }}</label>
<select class="form-control" id="select-colors">
<option value="0">All</option>
#foreach($colors as $color)
<option value="{{ $color->id }}">{{ $color->name }}</option>
#endforeach
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Sizes') }}</label>
<select class="form-control" id="select-sizes">
<option value="0">All</option>
#foreach($sizes as $size)
<option value="{{ $size->id }}">{{ $size->name }}</option>
#endforeach
</select>
</div>
</div>
And then I use JQuery to send a AJAX request to my controller with the current selected option values of all three dropdowns.
Example data:
Categories: All
Colors: Red
Sizes: Small
Now I wish to show the products with the color red and size small but the category doesn't matter.
I get the collections with the use of one to many relationships and link tables.
$product->categories
$product->colors
$product->sizes
I am not sure how to approach this.
You can do something similar to below:
public function index(ProductRequest $request)
{
$query = Product::where($request->validated());
return ProductResource::collection($query);
}
and in your ProductRequest you can define filters that you want to allow
class ProductRequest extends FormRequest
{
...
public function rules()
{
return [
'categories' => 'exists:categories,id'
....
];
}
On the Edit view I have a Select field and I want that select field to have the saved value for a given Model to be selected.
mediaController.php
public function edit($id)
{
//
$media = Media::find($id);
$categories = Category::lists('category', 'id');
return view('medias.edit-media')->with('media', $media)->with('categories', $categories);
}
edit.blade.php
<div class="form-group">
{!! Form::select('categories', $categories, $media->category ) !!}
</div>
On the index view (i.e the first Media as a Category of Video)
On the edit view (the first Media doesn't have the Category 'Video' selected)
even if I change my edit.blade.php to this: ...
<div class="form-group">
<label>Category of Upload
<select name="category" id="category" class="form-control input-sm">
#foreach($categories as $category)
<option value="{{ $category }}" {{ Input::old($media->category) == $category ? 'selected' : '' }}>{{ $category }}</option>
#endforeach
</select>
</label>
</div>
I still have the same result (the right Category is not selected)
<div class="form-group"><label>Category of Upload <select name="category" id="category" class="form-control input-sm"> #foreach($categories as $category) <option value="{{ $category->id }}" {{ $media->categories == $category->id ? 'selected' : '' }}>{{ $category }}</option>#endforeach </select> </label></div>
How would I keep my data in my select box when going back and editing a product?
Here is my form with parent and sub-categories:
<form role="form" method="POST" action="{{ route('admin.product.update', $product->id) }}">
{{ csrf_field() }}
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group{{ $errors->has('category') ? ' has-error' : '' }}">
<label>Parent Category</label>
<select class="form-control" name="category" id="category" data-url="{{ url('api/dropdown')}}">
<option value=""></option>
#foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->category }}</option>
#endforeach
</select>
#if($errors->has('category'))
<span class="help-block">{{ $errors->first('category') }}</span>
#endif
</div>
<br>
</div>
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group{{ $errors->has('cat_id') ? ' has-error' : '' }}">
<label>Sub-Category Category</label>
<select class="form-control" name="cat_id" id="sub_category">
<option value=""></option>
</select>
#if($errors->has('cat_id'))
<span class="help-block">{{ $errors->first('cat_id') }}</span>
#endif
</div>
<br>
</div>
<div class="form-group col-md-12">
<button type="submit" class="btn btn-primary waves-effect waves-light">Edit Product</button>
</div>
</form>
Here is my function to get the results to edit form:
/**
* Return the view to edit & Update the Products
*
* #param $id
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function editProduct($id) {
// Find the product ID
$product = Product::findOrFail($id);
// Get all Categories where parent_id = NULL
$categories = Category::whereNull('parent_id')->get();
// Return view with products and categories
return view('admin.product.edit', compact('product', 'categories'));
}
Here is my Category Model for my categories and sub categories:
class Category extends Model {
protected $table = 'categories';
protected $fillable = ['category'];
/**
* One sub category, belongs to a Main Category ( Or Parent Category ).
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function parent() {
return $this->belongsTo('App\Category', 'parent_id');
}
/**
* A Parent Category has many sub categories
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function children() {
return $this->hasMany('App\Category', 'parent_id');
}
/**
* One Category can have many Products.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function product() {
return $this->hasMany('App\Product', 'id');
}
}
Here is my Product Model for my products table:
class Product extends Model {
protected $table = 'products';
protected $fillable = [
'product_name',
'price',
'cat_id',
'featured',
'brand_id',
];
/**
* One Product can have one Category.
*
* #return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function category() {
return $this->hasOne('App\Category', 'id');
}
}
And here is how my categories and products table is set up:
Just to let you know, when I choose a parent category, a ajax call fires off and retrieves all the parent sub-categories. I have not included that in this question.
For Creation forms:
#foreach($categories as $category)
<option value="{{ $category->id }}" #if(old('category')&&old('category')== $category->id) selected='selected' #endif >{{ $category->category }}</option>
#endforeach
For edit forms:
#foreach($categories as $category)
<option value="{{ $category->id }}" #if($category->id==$model->category) selected='selected' #endif >{{ $category->category }}</option>
#endforeach
make this change and try
<div class="form-group">
<label>Parent Category</label>
<select class="form-control" name="category" id="category" data-url="{{ url('api/dropdown')}}" >
<option value=""></option>
#foreach($categories as $category)
<option value="{{ $category->id }}" {{$product->Category->parent->id == $category->id ? "selected" : "" }}>{{ $category->category}}</option>
#endforeach
</select>
<br>
</div>
First make sure your input gets redirected back to the form:
return redirect('form')->withInput();
Then check the key with your old input data:
#foreach($categories as $category)
<option value="{{ $category->id }}" {{ ($category->id == old('category') ? 'selected="selected"' : '') }}>{{ $category->category }}</option>
#endforeach
This is an explanation to #LewiG's answer.
When creating an item we return the input if it's invalid, in which case we should prepare our views to handle old($key) input.
So for our particular <select></select> tags we compare the options against the old input.
e.g.
#foreach($categories as $category)
<option value="{{ $category->id }}" #if(old('category')&&old('category')== $category->id) selected='selected' #endif >{{ $category->category }}</option>
#endforeach
When we edit an item, for example a product that has a category,
we pre-select the current category by comparing the category_id property (for example) in our product.
e.g.
#foreach($categories as $category)
<option value="{{ $category->id }}" #if($category->id==$product->category_id) selected='selected' #endif >{{ $category->category }}</option>
#endforeach
Now where does the $product or $model or $whatever comes from?
Database, Eloquent, query, or just an object that you've created
then we return it to the view using
return view('product.edit')->withProduct($product);
or
return view('product.edit')->with('product',$product);
in my controller, I am passing a list of clients to the view
public function edit(Project $project)
{
$clients = Client::select('clientName', 'id')->get();
return View::make('projects.edit', compact('project', 'clients'));
}
Now in my view, I am currently doing this
<div class="form-group">
{!! Form::label('clientName', 'Client Name:', array('class' => 'col-sm-5 control-label blue')) !!}
<div class="col-sm-7">
<select class="clientName" name="clientName">
#foreach($clients as $client)
#if (Input::old('clients') == $client->id)
<option value="{{ $client->id }}" selected="selected">{{ $client->clientName }}</option>
#else
<option value="{{ $client->id }}">{{ $client->clientName }}</option>
#endif
#endforeach
</select>
</div>
</div>
What I am trying to do is have the default select option set as the old input. At the moment, the select displays with all the clients, but the old value is not default.
How would I go about making it the default option?
Thanks
Update
I do a alternative way I am trying. In my edit function I do
public function edit(Project $project)
{
$clients = Client::lists('clientName', 'id');
return View::make('projects.edit', compact('project', 'clients'));
}
And then in my view I do
<div class="form-group">
{!! Form::label('clientName', 'Client Name:', array('class' => 'col-sm-5 control-label blue')) !!}
<div class="col-sm-7">
{!! Form::select('clientName', $clients, Input::old('clients'), ['class' => 'clientName']) !!}
</div>
</div>
Seem to have the same issue though, the client is not the old client as the default selected option.
Thanks
Your select name is clientName but your old input is looking to a field with the name clients.
The following should work:
<option value="{{ $client->id }}" {!! old('clientName', $project->client->id) == $client->id ? 'selected="selected"' : '' !!}>{{ $client->clientName }}</option>