Laravel 9: how to use enums in blade (<select>)? - php

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

Why are some of my request parameters sent as `null` to my controller?

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');
}

Error on multi select when using Laravel Livewire

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.

Laravel Model binding many to many realtionship does not populate data

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>

Laravel Form Building Not Passing Array Of Items

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>

laravel get value from array of controllers

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'];

Categories