How can I get value from a select field? - laravel

I have a livewire CRUD component to make posts. It worked perfectly before I tried to add a choice of categories. This is a piece of code, where I try to choose a category:
<select class="form-select" aria-label="Default select example">
<option wire:model="category_id" selected>Выберите категорию</option>
#foreach($categories as $category)
<option value="{{ $category->id }}">
{{ $category->name }}
</option>
#endforeach
#error('category_id') <span class="text-red-500">{{ $message }}</span>#enderror
</select>
I can display all the categories and choose one, but I can't get it in the component. I have tried to use a checkbox element. I was even validated, whenever I chose a category or not. The select field isn't validated at all. I can just output all the categories from the db.
Here is my CRUD component.
<?php
namespace App\Http\Livewire;
use App\Models\Category;
use Livewire\Component;
use App\Models\Post;
use Livewire\WithPagination;
use Livewire\WithFileUploads;
class Posts extends Component
{
public $title, $categories, $category_id, $body, $post_id, $search, $img;
public $isOpen = 0;
use WithFileUploads;
use WithPagination;
public function mount()
{
$this->categories = Category::all();
}
public function render()
{
$search = '%' . $this->search . '%';
$posts = Post::where('title', 'LIKE', $search)
->orWhere('body', 'LIKE', $search)
->latest()
->paginate(5);
return view('livewire.posts.posts', ['posts' => $posts])->layout('layouts.app');
}
public function create()
{
$this->resetInputFields();
$this->openModal();
}
public function openModal()
{
$this->isOpen = true;
}
public function closeModal()
{
$this->isOpen = false;
}
private function resetInputFields()
{
$this->category_id = '';
$this->title = '';
$this->body = '';
$this->post_id = '';
}
public function store()
{
$this->validate([
'category_id' => 'required',
'title' => 'required',
'body' => 'required',
'img' => 'image|max:1024'
]);
Post::updateOrCreate(
['id' => $this->post_id],
['category_id' => $this->category_id,
'title' => $this->title,
'body' => $this->body,
'img' => $this->img->hashName(),
]);
if(!empty($this->img)) {
$this->img->store('public/docs');
}
session()->flash('message',
$this->post_id ? 'Пост успешно обновлен.' : 'Пост успешно создан.');
$this->closeModal();
$this->resetInputFields();
}
public function edit($id)
{
$post = Post::findOrFail($id);
$this->category_id = $post->category_id;
$this->post_id = $id;
$this->title = $post->title;
$this->body = $post->body;
$this->img = $post->img;
$this->openModal();
}
public function delete($id)
{
Post::find($id)->delete();
session()->flash('message', 'Пост успешно удален.');
}
}

Will setting a name for select solve the problem?
<select class="form-select" aria-label="Default select example" name="category_id">
<option wire:model="category_id" selected>Выберите категорию</option>
#foreach($categories as $category)
<option value="{{ $category->id }}">
{{ $category->name }}
</option>
#endforeach
#error('category_id') <span class="text-red-500">{{ $message }}</span>#enderror
</select>
Currently it doesn't seems like framework can identify the name for this input

Related

Trying to make select option to work in livewire

I am getting this error when I try to submit the selected option using Laravel Livewire.
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'team_id' cannot be null (SQL: insert into projects (user_id, name, description, team_id, updated_at, created_at) values (1, Sammy Mwangangi, qdqwfdweqfc wqdqwfdwqdqwdwq, ?, 2021-06-24 13:39:14, 2021-06-24 13:39:14))
App\Models\Project.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'team_id',
];
// protected $guarded = [];
public function tasks(){
return $this->hasMany(Task::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function team(){
return $this->belongsTo(Team::class);
}
}
App\Http\Livewire\Project.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Project;
use App\Models\Team;
use Livewire\WithPagination;
use Illuminate\Support\Str;
use Auth;
class Projects extends Component
{
use WithPagination;
public $name;
public $description;
public $team_id;
public $projectId = null;
public $showModalForm = false;
public function showCreateProjectModal()
{
$this->showModalForm = true;
}
public function updatedShowModalForm()
{
$this->reset();
}
public function storeProject()
{
$this->validate([
'name' =>'required',
'description' => 'required',
]);
$project =new Project();
$project->user_id = auth()->user()->id;
$project->name = $this->name;
$project->description = $this->description;
$project->team_id = $this->team_id;
$project->save();
$this->reset();
session()->flash('flash.banner', 'Project created Successfully');
}
public function showEditProjectModal($id)
{
$this->reset();
$this->showModalForm = true;
$this->projectId = $id;
$this->loadEditForm();
}
public function loadEditForm()
{
$project = Project::findOrFail($this->projectId);
$this->name = $project->name;
$this->description = $project->description;
}
public function updateProject()
{
$this->validate([
'name' =>'required',
'description' => 'required',
]);
Project::find($this->projectId)->update([
'name' => $this->name,
'description' => $this->description
]);
$this->reset();
session()->flash('flash.banner', 'Project Updated Successfully');
}
public function deleteProject($id)
{
$project = Project::find($id);
$project->delete();
session()->flash('flash.banner', 'Project Deleted Successfully');
}
public function render()
{
return view('livewire.projects', [
'projects' => Project::orderBy('created_at', 'DESC')->paginate(5),
'teams' => Team::all()
]);
}
}
projects.blade.php
<div class="flex flex-wrap mb-6">
<label for="team" class="block text-gray-700 dark:text-white text-sm font-bold mb-2">
{{ __('Team') }}:
</label>
<select class="form-select px-4 py-3 w-full rounded" wire:model="team_id" name="team_id">
#foreach($teams as $team)
<option value="{{$team->id}}">{{$team->name}}</option>
#endforeach
</select>
<p class="mt-2 text-sm text-gray-500">
Select the team/department your project is associated with.
</p>
#error('team_id')
<p class="text-red-500 text-xs italic mt-4">
{{ $message }}
</p>
#enderror
</div>
What am I missing? I haven't done much with livewire regarding model relationships and how to bind data between the models.
you must do a default tag option for select, this way on change element this will bind the value to the property
<select class="form-select px-4 py-3 w-full rounded" wire:model="team_id">
<option>Select Team</option>
#foreach($teams as $team)
<option value="{{$team->id}}">{{$team->name}}</option>
#endforeach
</select>
also in the validation rules you can add another for the "team_id" value that can't be null on submit
wire:model should be on option tag not on select

Laravel Excel : error Resource interpreted as Document but transferred with MIME

Laravel Excel to export data will download empty data with only headers in excel sheet! I want to export only the filtered data from my search using excel but it will download an empty excel sheet only with headers!! please can anyone tell me where is my error!
DealerExportSearch.php
class DealersSearchExport implements FromCollection, WithHeadings, ShouldAutoSize, WithEvents
{
use Exportable;
protected $name;
protected $email;
protected $mobile_no;
protected $city;
public function __construct( $name, $email, $mobile_no , $city)
{
$this->name = $name;
$this->email = $email;
$this->mobile_no = $mobile_no;
$this->city = $city;
}
//function select data from database
public function collection()
{
return Dealer::select()->where('name', $this->name)
->where('email', $this->email)
->where('mobile_no', $this->mobile_no)
->where('city', '=', $this->city) //i tried using the above and this also same result
->get();
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$cellRange = 'A1:W1'; // All headers
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(12);
},
];
}
//function header in excel
public function headings(): array
{
return [
'No',
'name',
'email',
'mobile_no',
'shop_name',
'city',
'address'
];
}
}
my controller
public function index(Request $request)
{
$method = $request->method();
if ($request->isMethod('get')) {
$name = $request->name;
$email = $request->email;
$city = $request->city;
$mobile_no = $request->mobile_no;
if ($request->has('search')) {
$dealers = Dealer::where('name', 'LIKE', '%'.$name.'%')
->where('email', 'LIKE', '%'.$email.'%')
->where('mobile_no', 'LIKE', '%'.$mobile_no.'%')
->where('city', 'LIKE', '%'.$city.'%')
->paginate(5);
return view('dealer.index', compact('dealers'));
}
elseif ($request->has('exportSearchExcel')) {
return Excel::download(new DealersSearchExport($name ?? '', $email ?? '', $mobile_no ?? '', $city ?? ''), 'DealersSearchExcel-reports.xlsx');
}
else{
$dealers = Dealer::orderBy('id', 'DESC')->paginate(5);
return view('dealer.index', compact('dealers'));
}
}
}
blade
<form action="{{ route('dealer.index') }}" method="GET" enctype="multipart/form-data">
#csrf
<div class="form-group row">
<div class="col-sm-3">
<label for="name">Name: </label>
<input class="form-control" name="name" value="{{ request()->input('name') }}" type="text" placeholder="The Dealer Name">
</div>
.....................................................................
</div>
<div class="col-md-12 pt-3 text-right">
<button type="submit" name="search" class="btn btn-primary"><i class="fa fa-fw fa-search"></i> Search</button>
<button type="submit" name="exportSearchExcel" class="btn btn-secondary text-light"><i class="fa fa-download"></i> Export Excel </button>
</div>
</div>
No error is showing just in my console it will return this error and download an empty xslx whenever I press the export button.
Resource interpreted as Document but transferred with MIME type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: "http://127.0.0.1:8000/dealer?_token=TTlpqFNn4hr5rwI1jSlt0d4mbtww2moO8i1WWjfn&name=&email=&mobile_no=&exportSearchExcel=".
Update
I fixed it by changing my query in DealerExportSearch.php to the same query that I have in controller then it worked
DealerExportSearch.php
class DealersSearchExport implements FromCollection, WithHeadings, ShouldAutoSize, WithEvents , WithMapping
{
//the above codes not changed till the collection function
//function select data from database
public function Collection()
{
return Dealer::where('name', 'LIKE', '%'.$this->name.'%')
->where('email', 'LIKE', '%'.$this->email.'%')
->where('mobile_no', 'LIKE', '%'.$this->mobile_no.'%')
->where('city', 'LIKE', '%'.$this->city.'%')
->get();
}
public function map($row): array{
$fields = [
$row->id,
$row->name,
$row->gender,
$row->date_of_birth,
$row->email,
$row->mobile_no,
$row->shop_name,
$row->city,
$row->address,
];
return $fields;
}
///below codes not changed .....

Test Driven Laravel : Invalid Argument supplied for foreach

So i have a form with multiple fields like below
<ul class="list-group list-group-flush">
#foreach ($group as $perm)
<li class="list-group-item">{{$perm->name}}
<div class="float-right">
<select name="perms[{{$perm->id}}]" class="form-control">
<option value="1">Yes</option>
<option value="0" selected>No</option>
</select>
</div>
</li>
#endforeach
</ul>
My controller is like below
public function permission(int $id)
{
$permission = request()->perms;
foreach ($permission as $perm => $status)
{
if($status == 1)
{
//echo $perm . " " . $status;
$user_perm = User_perms::create([
'user_id' => $id,
'perm_id' => $perm,
]);
}
}
$user = Users::find($id);
return redirect($user->path());
}
This code does what I want but I have a test
public function permissions_applied_for_user()
{
$this->withoutExceptionHandling();
//create a user
$this->post('/users/add', $this->data());
$user = Users::first();
//first clear out all data from user_perm table for specific user
$response = $this->post('/users/permission/' . $user->id, [
'user_id' => $user->id,
'perm_id' => '1',
]);
$this->assertCount(1, User_perms::all());
$response->assertRedirect('/users/view/' . $user->id);
//$response->assertOk();
//second insert all new permissions into the table
}
which throws the exception invalid argument supplied for foreach any advice on what I'm doing wrong?

Laravel many to many relationship update

I have some hard time with many to many relationship when I try to update the pivot columns.
Here is my database 'order_product' table
order_product_table
First, I am trying to update the products of that order.
Order update form
Here is the HTML:
#if($products)
<select class="form-control kt-select2 products" name="products[]" required>
<option selected disabled>Select a product</option>
#foreach($products as $product)
<option value="{{ $product->id }}" data-price="{{ $product->selling_price }}" {{ $product->id === $order_product->id ? 'selected' : '' }}>{{ $product->name }}</option>
#endforeach
</select>
#endif
My spaghetti code...
public function update(Order $order)
{
$attributes = $this->validateOrder();
$order->update($attributes);
$products = \request('products');
$quantity = \request('quantity');
$price = \request('price');
$discount = \request('discount');
$total = 0;
if ($products) {
$order->products()->sync([$order->id => ['product_id' => $products]]);
}
$this->flashMessage('success', 'Your order was updated with success!');
return redirect()->back();
}
Try a lot of things, but it does not work ...
Edit your code like this:
public function update(Order $order)
{
$attributes = $this->validateOrder();
$order->update($attributes);
//should be an array of products ID
$products = \request('products');
$quantity = \request('quantity');
$price = \request('price');
$discount = \request('discount');
$total = 0;
foreach($products as $key => $productId) {
//normalize attributes
$attributes = [
'price' => $price[$key],
'quantity' => $quantity[$key],
'discount' => $discount[$key],
];
$order->products()->updateExistingPivot($productId, $attributes);
}
$this->flashMessage('success', 'Your order was updated with success!');
return redirect()->back();
}
For more information about updateExistingPivot() method, check Laravel documention
For the sync() method in many to many relation, you need to provide the relation ID as index of the array.
$syncable = [];
foreach ($products as $key => $productId) {
$syncable[$productId] = [
'price' => $attributes['price'][$key],
'quantity' => $attributes['quantity'][$key],
'discount' => $attributes['discount'][$key]
]
}
if ($syncable) {
$order->products()->sync($syncable);
}

Laravel. Controller not getting the values from the Form

The controller is not getting the data from the FORM. I realise that the Form has by default a Post method, while the Route is using a Get, but if I change that, then the form will not display the form fields. Validation fails as the "required" does not get any values, so it returns to the same page. If I remove the validation filter, then it does go to the results page, but all it does is show ALL of the content of the table, since it is getting no parameters (where) from the Form. The weird thing is that in the past, it worked, but I must have messed up with some part of the code and now it doesn't. To save space here I have left out many fields which dont play a role in the problem.
The Form has three interdependent Fields Country, Region and Town, which are filled up alright.
FORM:
<form action = "{{URL::route('sacapropiedades')}} "class="form-horizontal" id="my_form" name="my_form">
<div class="form-group">
<div class="col-sm-3">
<label for="country">Pays</label>
<select name ="country" {{ (Input::old('country')) ?' value ="' . e(Input::old('country')). '"' : '' }} id = "country" class="form-control">
#foreach($countries as $country)
<option value="{{$country->country}}">{{$country->country}}</option>
#endforeach
</select>
</div>
<div class="col-sm-3">
<label for="town">Ville</label>
<select name ="town" {{ (Input::old('town')) ?' value ="' . e(Input::old('town')). '"' : '' }}id = "town" class="form-control">
</select>
</div>
</div><!-- END OF THIRD FORMGROUP -->
<div class="form-group">
<div class="col-sm-4">
</div>
<div class="col-sm-2">
<button type="submit" class="btn btn-success">Enviar</button>
<button type="reset" class="btn btn-danger">Borrar</button>
</div>
</div>
</form>
ROUTES
Route::get('realestate/listproperty', array(
'as' =>'sacapropiedades',
'uses' =>'countriesregionstownsController#findproperty'
));
CONTROLLER
public function findproperty(){
/*IT REPEATS THE COUNTRY QUERY ABOVE BECAUSE IT IS GOING TO USE IT
*ON THE RESULTS PAGE AND IT GIVES THE USER TO SELECT AGAIN OTHER COUNTRIES
*WITHOUT HAVING TO RETURN TO THE FIRST PAST PAGE*/
$countries = DB::table('properties')
->select('country')
->distinct()
->get();
/*FIRST VALIDATE INPUT DATA*/
$validator = Validator::make(Input::all(),
array(
'country' =>'required',
'regions' =>'required',
'transaction' =>'required',
'town' =>'required'
));
if($validator->fails()){
return Redirect::route('showrealestate')
->withErrors($validator)
->withInput();
}
else{
$country = Input::get('country');
$region = Input::get('regions');
$town = Input::get('town');
$transaction = Input::get('transaction');
$pricefrom = Input::get('pricefrom');
$priceto = Input::get('priceto');
$roomsfrom = Input::get('roomsfrom');
$roomsto = Input::get('roomsto');
$builtyear = Input::get('builtyear');
$swimming = Input::get('swimming');
$garden = Input::get('garden');
$garage = Input::get('garage');
$message = Input::get('message');
}
$country = DB::table('countries')->where('id_pais', $country)->pluck('nombre_pais');
$region = DB::table('regions')->where('id_region', $region)->pluck('nombre_region');
$town = DB::table('cities')->where('id_localidad', $town)->pluck('nombre_localidad');
$users = DB::table('users')
->join('properties', 'users.id', '=', 'properties.id_user_fk')
->select('users.email', 'properties.id_user_fk', 'properties.country', 'properties.region', 'properties.town',
'properties.price', 'properties.rooms','properties.m2','properties.swimming',
'properties.garden','properties.garage','properties.builtyear','properties.message',
'properties.pic1',
'properties.pic2', 'properties.pic3','properties.pic4','properties.pic5','properties.pic6');
if (!empty($country)) {
$users = $users->where('country', '=', $country);
}
if (!empty($region)) {
$users = $users->where('region', '=', $region);
}
if (!empty($town)) {
$users = $users->where('town', '=', $town);
}
if (!empty($transaction)) {
$users = $users->where('transaction', '=', $transaction);
}
if (!empty($pricefrom)) {
$users = $users->where('price', '>', $pricefrom);
}
if (!empty($priceto)) {
$users = $users->where('price', '<', $priceto);
}
if (!empty($roomsfrom)) {
$users = $users->where('rooms', '>', $roomsfrom);
}
if (!empty($roomsto)) {
$users = $users->where('rooms', '<', $roomsto);
}
if (!empty($builtyear)) {
$users = $users->where('builtyear', '>', $builtyear);
}
if (!empty($swimming)) {
$users = $users->where('swimming', '=', $swimming);
}
if (!empty($garage)) {
$users = $users->where('garage', '=', $garage);
}
if (!empty($garden)) {
$users = $users->where('garden', '=', $garden);
}
if (!empty($message)) {
$users = $users->where('message', '=', $message);
}
$users = $users->get();
return View::make('realestate.externa.listproperty', compact('users','countries'));
}
A post method is mandatory, otherwise Laravel will not redirect it to the correct method with the correct data. How was it working before? By luck, probably. :)
Route::get('realestate/listproperty', array(
'as' =>'sacapropiedades',
'uses' =>'countriesregionstownsController#findproperty'
));
Route::post('realestate/listproperty', array(
'as' =>'sacapropiedades',
'uses' =>'countriesregionstownsController#findproperty'
));
or
Route::match(array('GET', 'POST'), 'realestate/listproperty', array(
'as' =>'sacapropiedades',
'uses' =>'countriesregionstownsController#findproperty'
));
or
Route::any('realestate/listproperty', array(
'as' =>'sacapropiedades',
'uses' =>'countriesregionstownsController#findproperty'
));
Then you'll probably need to not validate on GET:
if (Request::getMethod() == 'POST')
{
$validator = Validator::...
}
EDIT:
Sorry I overlooked this problem:
Instead of writing your FORM tag manually, use Laravel's FormBuilder class:
<?php Form::open(array('route' => 'sacapropiedades', 'class' => 'form-horizontal', 'id' => 'my_form', 'name' => 'my_form')); ?>
The difference is that it will add the method for you and it will also add a csrf token to your form.

Resources