I read this awesome article before asking here.
I created an enum class CaseSeverity to use across all forms that needs it. I couldn't find a way to use the enum within the blade, specifically listing the cases within <select> options.
I did a workaround by mkaing a static function in the enum class:
public static function option()
{
return [
'high' => 'high',
'medium' => 'medium',
'low' => 'low'
];
}
Then made a helper function to fetch the array:
if(!function_exists('case_severity')) {
// Get case severity enum
function case_severity() {
return CaseSeverity::option();
}
}
Then used that in the blade:
<select class="form-select #error('severity') is-invalid #enderror"
name="severity" required
data-control="select2"
data-placeholder="Select"
data-hide-search="true">
<option></option>
#foreach (case_severity() as $item)
<option value="{{ $item }}"> {{ $item }} </option>
#endforeach
</select>
Yes, it working as I want it to be, but I have a strong feeling that there is a better way of doing it? Because to me the code/enum cases are repeated.
Entire enum class:
enum CaseSeverity : string
{
case High = 'high';
case Medium = 'medium';
case Low = 'low';
// Coloring the cases to use in datatables as badges
public function color(): string
{
return match($this)
{
self::High => 'badge-danger',
self::Medium => 'badge-warning',
self::Low => 'badge-success',
};
}
// To use in <select> fields
public static function option()
{
return [
'high' => 'high',
'medium' => 'medium',
'low' => 'low'
];
}
}
You could do it like this if you like it bettter.
In your App\Enums\Severity file:
public static function values(): array
{
return array_column(self::cases(), 'name', 'value');
}
Then you can loop through the values:
#foreach(App\Enums\Severity::values() as $key=>$value)
<option value="{{ $key }}">{{ $value }}</option>
#endforeach
Related
I'm developing a LiveWire/Laravel project and in my product.blade.php, the category_id is sent as null to the store function. Apparently there is no problem in my input and my model and category_id is defineded in my component.
I used some artisan comands related to clearing the cache and config and even I created another component with different name but I met same bug
dd:
array:8 [▼
"title" => "تراکت"
"en_title" => "tracket"
"category_id" => null
"description" => "nothing"
"status" => 1
"img" => null
"price" => "48000"
"keywords" => "tracket"
]
Livewire Product Blade:
<div class="form-group">
<label class="form-label">دسته بندی محصول</label>
<select wire:model="category_id" id="select-countries" class="form-control custom-select">
#foreach($categories as $category)
<option value="{{$category->id}}">{{$category->title}}</option>
#if(count($category->childrenRecursive) >0)
#include('Admin.category.partials',['categories'=>$category->childrenRecursive,'level'=>1,'create'=>1])
#endif
#endforeach
</select>
</div>
Livewire Component :
<?php
class Index extends Component
{
public $title,$en_title,$category_id,$description,$status=1,$img=null,$price,$keywords;
public function store(){
$keywords=serialize(explode(",",$this->keywords));
Product::create([
'title'=>$this->title,
'en_title'=>$this->en_title,
'category_id'=>$this->category_id,
'description'=>$this->description,
'status'=>$this->status,
'price'=>$this->price,
'image'=>$this->img,
'keywords'=>$keywords,
]);
$this->reset(['title','en_title','category_id','description','price']);
session()->flash('add_product','محصول شما با موفقیت اضافه شد');
}
public function render()
{
$categories=Category::with('childrenRecursive')->where('parent_id',null)->get();
$products=Product::latest()->paginate(8);
return view('livewire.admin.product.index',compact('categories','products'))->extends('layouts.admin')->section('content');
}
}
Your syntax appears correct and I suspect you're sometimes seeing null because you're not setting an initial value for $category_id. Therefore, if you don't select an option from your select element and submit your form, the value of $category_id will be null.
You can perform some component initialization in the mount method where I suggest you set an initial value for your public properties:
public $categories, $products;
public $category_id;
public function mount()
{
$this->categories = Category::with('childrenRecursive')
->where('parent_id', null)
->get();
$this->products = Product::latest()->paginate(8);
$this->category_id = $this->categories->first()->id;
}
public function render()
{
return view(
'livewire.admin.product.index',
compact('categories','products')
)
->extends('layouts.admin')
->section('content');
}
I'm using choices.js to have multiple select options in my Laravel project. However, I'm currently having an error Attempt to read property "id" on string.
PostController
public function new()
{
$tags = TagQuery::all();
return view('threads.new', compact('tags'));
}
new.blade.php
<livewire:editor :title="null" :tags="$tags" :body="null" />
livewire/editor.blade.php
#if($errors->has('tags'))<span class="text-pink-600 text-sm">{{ $errors->first('tags') }}</span>#endif
<select id="tags" multiple #if($errors->has('tags')) class="border-pink-600" #endif wire:model="tags">
#foreach($tags as $tag)
<option x-cloak value="{{ $tag->id }}">{{ $tag->name }}</option>
#endforeach
</select>
Editor.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Editor extends Component
{
public $title;
public $tags;
public $body;
protected $rules = [
'title' => ['required', 'min:5', 'max:70'],
'body' => ['required', 'min:10', 'max:50000'],
'tags' => ['required', 'array', 'min:1', 'max:3'],
'tags.*' => ['exists:tags,id']
];
public function render()
{
return view('livewire.editor');
}
public function submit()
{
$this->validate();
return dd($this->title, $this->body, $this->tags);
}
}
How do I fix this issue? The code is working if submitted as normal form (without livewire). I need to use Livewire since I'm also using tiptap headless editor and I cannot pass the value of the editor from livewire to regular laravel request.
I have two tables with a many to many relation (Project and Center, the pivot table is ProjectCenter).
These are my models:
Project:
class Project extends Model {
public function centers()
{
return $this->belongsToMany('App\Models\Center', 'ProjectCenter', 'IDProject', 'IDCenter');
}
public function getCenterListAttribute()
{
return $this->centers->lists('IDCenter')->all();
}
}
Center:
class Center extends Model {
public function projects()
{
return $this->belongsToMany('App\Models\Project', 'ProjectCenter', 'IDCenter', 'IDProject');
}
}
Controller -> edit:
public function edit($id)
{
$project = Project::find($id);
$centerList = Center::lists('Name', 'IDCenter')->toArray();
return view('project/add', array('centerList' => $centerList))->with('project', $project);
}
And the view:
{!! Form::label('centers_list', 'Center*') !!}
{!! Form::select('centers_list[]',
$centerList,
null,
array(
'class' => 'form-control ',
'required' => 'required',
'multiple' => true,
'data-placeholder' =>
'Select a center'
)
) !!}
But I can not select the data already stored previously.
For example: the project 8 (IDProject) has two centers (1 and 2) but the data is not populated in the multiple select:
What am I doing wrong?
You all time get same result $centerList = Center::lists('Name', 'IDCenter')->toArray(); but you must be get product centers using query with model.
$project = Project::with("centers:Name,IDCenter")->find($id);
$centerList = $project->centers->pluck('Name', 'IDCenter')->toArray();
I already solve the problem using a foreach to select the related centers:
<select multiple="multiple" name="centers[]" id="centers" class="form-control select2" required="required" data-placeholder="Select a center">
#if($centerList)
#foreach($centerList as $key => $center)
<option value="{{$key}}" {{ (collect($selectedCenters)->contains($key)) ? "selected='selected'" : '' }} >{{$center}}</option>
#endforeach
#endif
</select>
I passed my tags and on my form I have a multi-select. Although when I do tags[] nothing gets passed in. If I do just tag then only one of them submits.
public function create()
{
$categories = Category::pluck('name', 'id');
$tags = Tag::pluck('name', 'id');
return view('posts.create')->withCategories($categories)->withTags($tags);
}
{{ Form::label('tags', "Select Tag")}}
{{ Form::select('tags[]', $tags, null, ['class' => 'selectpicker', 'multiple', 'data-live-search="true"', 'data-actions-box="true"', 'data-width="100%', 'show-menu-arrow']) }}
It could be a glitch in the current version Laravel / Form Builder. If you do the old fashion select way it works as it should.
public function create()
{
$categories = Category::pluck('name', 'id');
$tags = Tag::all();
return view('posts.create')->withCategories($categories)->withTags($tags);
}
<select name="tags[]" class="selectpicker show-tick" multiple data-live-search="true" data-actions-box="true" show-menu-arrow>
#foreach ($tags as $tag)
<option value="{{$tag->id}}">{{$tag->name}}</option>
#endforeach
</select>
this is my PermissionController.php
foreach (Route::getRoutes() as $route)
{
$action = $route->getAction();
if (array_key_exists('controller', $action))
{
$controllers[] = $action['controller'];
}
}
return view('permission.create')->withControllers($controllers);
and my permission/create/php is like this :
{!! Form::select('class_name[]', $controllers, null, ['class' => 'form-control', 'multiple']) !!}
here in controller, it put the name of all controllers in $controller and send it to the blade but when i select some of them, the request gives me their keys instead of value
public function store(Request $request)
{
return $request->get('class_name');
}
if I select the first one and third one the output is for example :{"1","3"}
but I want their value like this : {"UserController.php", "TestController.php"}
use this code instead Forms::Select or create your custom List with Laravel built-in List Function :
<select name="class_name[]" multiple>
#foreach($controllers as $class)
<option value="{{$class}}" >{{$class}}</option>
#endforeach
</select>
or simply replace the
$controllers[] = $action['controller'];
with
$controllers[$action['controller']] = $action['controller'];