Attempt to read property "name" on array (Select with Livewire) - laravel

I'm trying to make a dependent select with Livewire.
My problem is that when I load the second select, it loads it without problems, but when I select an option from the second select, it throws me this error.
Attempt to read property "nombre" on array
select template
<div class="container">
<div class="row mb-3">
<div class="col-4">
<label class="form-label">Tipo de Inscripcion</label>
<select wire:model="selectedTipoInscripcion" class="form-select">
<option selected>Seleccionar ...</option>
#foreach($tipoInscripcion as $tipo)
<option value="{{ $tipo -> id }}">{{ $tipo -> nombre}}</option>
#endforeach()
</select>
</div>
#if(!is_null($tipoPrograma))
<div class="col-4">
<label class="form-label">Tipo de Programa</label>
<select wire:model="selectedTipoPrograma" class="form-select">
<option selected>Seleccionar ...</option>
#foreach($tipoPrograma as $tipo)
<option value="{{ $tipo -> id}}">{{ $tipo -> nombre}}</option>
#endforeach()
</select>
</div>
#endif
</div>
</div>
The problem is in
<option value="{{ $tipo -> id}}">{{ $tipo -> nombre}}</option>
My Component
<?php
namespace App\Http\Livewire;
use App\Models\Curso;
use App\Models\Programa;
use Livewire\Component;
class SelectAnidado extends Component
{
public $selectedTipoInscripcion = null, $selectedTipoPrograma = null, $SelectedProgrCur = null;
public $tipoPrograma = null, $progrCur = null, $sw = null;
public function render()
{
$programa = (object) ['id' => 1, 'nombre' => 'Programa'];
$curso = (object) ['id' => 2, 'nombre' => 'Curso'];
$ti = collect([$programa, $curso]);
return view('livewire.select-anidado', [
'tipoInscripcion' => $ti
]);
}
public function updatedselectedTipoInscripcion($id)
{
if ($id == 1) {
$doctorado = (object) ['id' => 1, 'nombre' => 'doctorado'];
$maestria = (object) ['id' => 2, 'nombre' => 'maestria'];
$especialidad = (object) ['id' => 3, 'nombre' => 'especialidad'];
$diplomado = (object) ['id' => 4, 'nombre' => 'diplomado'];
$this->tipoPrograma = collect([$doctorado, $maestria, $especialidad, $diplomado]);
}
}
}
It tells me that I am trying to access an array as if it were an object.
But then the error should also appear when the is loaded.
Why does it only appear when I make the selection?

I think problem is here :
$this->tipoPrograma = collect([$doctorado, $maestria, $especialidad, $diplomado]);
you're passing array in tipoPrograma, and each variables is array too.

Related

My laravel livewire create form keeps giving me errors

LONG POST WARNING
why isn't my form to create a new user not working? im using laravel 9 and livewire. This is my code:
this is the button from where i show the model to create a form:
<div class="py-4 space-y-4">
<div class="flex justify-between px-2">
<div class="w-1/4">
<x-jet-input placeholder="search will go here"/>
</div>
<div>
<x-jet-button wire:click="create">New Skill</x-jet-button>
</div>
</div>
</div>
This is the model that shows the form. this model is also used to edit a skill as per Caleb the livewire creator:
<form wire:submit.prevent="save">
<x-jet-dialog-modal wire:model.defer="showEditModal">
<x-slot name="title">Edit Skill</x-slot>
<x-slot name="content">
<div class="col-span-6 sm:col-span-4">
<x-jet-label for="name" value="{{ __('Skill name') }}" />
<select wire:model="editing.name"
id="name"
type="text"
class="mt-1 block w-full border-gray-300
focus:border-indigo-300 focus:ring
focus:ring-indigo-200 focus:ring-opacity-50
rounded-md shadow-sm">
#foreach(\App\Models\Skill::LANGUAGES as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
#endforeach
</select>
<x-jet-input-error for="editing.name" class="mt-2" />
<x-jet-label for="years" value="{{ __('Years of experience') }}" class="mt-4"/>
<x-jet-input wire:model="editing.years" id="years" type="number"
min="{{\App\Models\Skill::MIN_YEARS_OF_EXPERIENCE}}"
max="{{\App\Models\Skill::MAX_YEARS_OF_EXPERIENCE}}"
class="mt-1 block w-full"
placeholder="Years of experience"/>
<x-jet-input-error for="editing.years" class="mt-2" />
</div>
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button wire:click="$set('showEditModal', false)" class="mr-2">Cancel</x-jet-secondary-button>
<x-jet-button type="submit">Save</x-jet-button>
</x-slot>
</x-jet-dialog-modal>
</form>
And this is my livewire component:
<?php
namespace App\Http\Livewire;
use App\Models\Skill;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class Skills extends Component
{
public $name ='';
public $showEditModal = false;
public Skill $editing;
public function rules()
{
return [
'editing.name' => 'required|in:'.collect(Skill::LANGUAGES)->keys()->implode(','),
'editing.years' => 'required|numeric|between:' . Skill::MIN_YEARS_OF_EXPERIENCE . ',' . Skill::MAX_YEARS_OF_EXPERIENCE,
];
}
public function render()
{
return view('livewire.skills', [
'skills' => Skill::where('user_id', auth()->id())->get(),
]);
}
public function mount(){
$this->editing = $this->makeBlankSkill();
}
public function makeBlankSkill(){
return Skill::make([
'name' => 'javascript',
'user_id' => auth()->user()->id,
]);
}
public function create(){
if ($this->editing->getKey()) $this->editing = $this->makeBlankSkill();
$this->showEditModal = true;
}
public function edit(Skill $skill) {
if ($this->editing->isNot($skill)) $this->editing = $skill;
$this->showEditModal = true;
}
public function save()
{
$this->validate();
$this->editing->save();
$this->showEditModal = false;
}
}
I keep getting SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value and i dont know why.
This is my modal:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Skill extends Model
{
use HasFactory;
const DEFAULT_OPTION = 'Please select a skill';
const LANGUAGES = [
'javascript' => 'JavaScript',
'php' => 'PHP',
'python' => 'Python',
'java' => 'Java',
'c#' => 'C#',
'c++' => 'C++',
'ruby' => 'Ruby',
'swift' => 'Swift',
'typescript' => 'TypeScript',
'rust' => 'Rust',
'go' => 'Go',
'kotlin' => 'Kotlin',
'scala' => 'Scala',
'dart' => 'Dart',
'r' => 'R',
'perl' => 'Perl',
'elixir' => 'Elixir',
'clojure' => 'Clojure',
'haskell' => 'Haskell',
'erlang' => 'Erlang',
'lisp' => 'Lisp',
'sql' => 'SQL',
'bash' => 'Bash',
'laravel' => 'Laravel',
'symfony' => 'Symfony',
'codeigniter' => 'CodeIgniter',
'yii' => 'Yii',
'zend' => 'Zend',
'cakephp' => 'CakePHP',
'fuelphp' => 'FuelPHP',
'slim' => 'Slim',
'lumen' => 'Lumen',
'phalcon' => 'Phalcon',
'silex' => 'Silex',
'express' => 'Express',
'koa' => 'Koa',
'hapi' => 'Hapi',
'meteor' => 'Meteor',
'angular' => 'Angular',
'ember' => 'Ember',
'react' => 'React',
'vue' => 'Vue',
'backbone' => 'Backbone',
'd3' => 'D3',
'threejs' => 'Three.js',
];
const MIN_YEARS_OF_EXPERIENCE = 1;
const MAX_YEARS_OF_EXPERIENCE = 50;
protected $fillable = [
'name', 'user_id', 'years'
];
public function user()
{
return $this->belongsTo(User::class);
}
}
Any help is greatly appriceated
I've done all there is to do.At least i hope. I've added the
$illable
array ive set the
'user_id' => auth()->user()->id,
Not sure what else im missing
public function save()
{
$this->validate();
$user = auth()->user();
$this->editing->user_id = $user->id;
$this->editing->save();
$this->showEditModal = false;
}
This was the answer for me
If user_id is null when creating a new Skill, this means there is no authenticated user. You can simply check by doing dd(auth()->id()). If you're logged in, this will return the primary key for your authentication model. If this is empty, you're simply not authenticated, and so you must first log in.
In the case your user_id is actually set, but it isn't arriving in your database upon saving, you'll have to check if the property user_id is correctly set on the Skill model's protected $fillable property.
If you dd($this->editing) right after mount, you can check the attributes of the model, and if the user_id is set, you know the error happens when saving to the database.
As it turns out, Livewire won't hydrate newly set properties on models. This is because Livewire "rehydrates" the models by simply re-fetching them from the database. This can be solved defining a rules property as shown here, directly relating to the model properties. This would ensure Livewire keeps the state of the updated properties.

Return Redirect Laravel

I want to return to the page with Link : localhost:8000/order/show/O1/T1.
O1 is $order->id_order and T1 is $trip->id_trip.
Here's my code.
Route::get('/order/show/{id_order}/{id_trip}', 'OrderController#show');
Route::get('/order/update_driver/{id_order}/{id_trip}', 'OrderController#update_driver');
Order Controller
public function show($id_order, $id_trip){
$trip = Trip::find($id_trip);
$order = Order::where(['id_order' => $id_order, 'id_trip' => $id_trip])->first();
$detail_order = Detail_Order::where(['id_order' => $id_order, 'id_trip' => $id_trip])->first();
$detail = Order::join('detail_order', 'order.id_order', '=', 'detail_order.id_order')
->where('order.id_order', $id_order)
->select('order.id_trip as order_trip',
'order.id_order as order_id',
'order.id_users as order_users',
'order.date_order as order_date',
'detail_order.id_seat as detail_seat',
'detail_order.users as detail_users')
->get();
$driver = Driver::all();
return view('travel.order.show', ['trip' => $trip, 'order' => $order, 'detail' => $detail, 'detail_order' => $detail_order, 'driver' => $driver]);
}
public function update_driver($id_order, $id_trip){
$driver = Input::get('id_users_driver');
Detail_Order::where('id_order', $id_order)
->update(['id_users_driver' => $driver]);
session()->flash('flash_success', 'Data has been updated');
return redirect('/order/show/{id_order}/{id_trip}');
}
View
<form method="get" action="/order/update_driver/{{ $order->id_order}}/{{ $order->id_trip}}">
<label>Driver</label>
<select class="form-control" name="id_users_driver" id="id_users_driver">
<option value=""> Driver </option>
#foreach($driver as $d)
<option value="{{$d->id_users}}"{{$detail_order->id_users_driver == $d->id_users ? 'selected' : ''}}>{{$d->name}}</option>
#endforeach
</select>
#if($errors->has('id_users_driver'))
<div class="text-danger">
{{ $errors->first('id_users_driver')}}
</div>
#endif
<input type="submit" class="btn btn-primary" value="Save">
</form>
It returned error Trying to get property 'id_order' of non-object.
Do you know how to make it return to localhost:8000/order/show/O1/T1? Thank you

How to define an onclick function on Laravel Collectives?

I have implemented a drop down using Laravel collectives. I need to call function setMaterialValue(let x){ console.log(x)} on each time I select a material. This should be specific to each material as cotton-10, wetlook-20, crocodile-30 etc. Without Laravel collective this can be performed as
<option onclick="setMaterialValue(10);">Cotton</option>
How to perform this using Laravel collectives?
My code is as follows:
<div class="card">
<div class="card-header"><h2 class="card-title m-0">Feature Selector</h2></div>
<div class="card-body">
<h5 class="card-title"><b>Material Selector</b></h5>
<div class="row">
<div class="col-md-6">
Textile Material
</div>
<div class="col-md-6">
{{Form::select('material_selector', [
'10' => 'Cotton',
'20' => 'Wet Look',
'30' => 'Crocodile',
], null, ['placeholder' => 'Select Material'],['class'=>'form-control'])
}}
</div>
</div>
<hr>
</div>
</div>
FYI - Where your class declaration is add it and any other html attributes there as well:
{{ Form::select('material_selector',
[
'1' => 'Cotton',
'2' => 'Wet Look',
'3' => 'Crocodile',
],
null,
['placeholder' => 'Select Material'],
[
'class'=>'form-control',
'onclick'=>'setMaterialValue(10)' // <== ADD IT HERE
])
}}
You should probably use jQuery. Then you can address your select element as follows
$(document).ready(function() {
$('.form-control[name="material_selector"]').on('change', showSelectedValue);
function showSelectedValue(event) {
var target = $(event.target);
console.log(target.val() + " = " + target.find('option:selected').text());
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="material_selector" class="form-control">
<option value="10">Cotton</option>
<option value="20">Wet Look</option>
<option value="30">Crocodile</option>
</select>
Another option
If you really do not want to use jQuery, then try to use the onChange attribute for the select tag like the example below
{{Form::select(
'material_selector', // name attribute of the select
['10' => 'Cotton', '20' => 'Wet Look', '30' => 'Crocodile'], // option values
null, // selected value, for example '20'
['placeholder' => 'Select Material', 'class' => 'form-control', 'onChange' => 'showSelectedValue(this)'], // attributes for <select>
)}}
function showSelectedValue(element) {
console.log(element.value + " = " + element.options[element.selectedIndex].text);
}
<select name="material_selector" class="form-control" onChange="showSelectedValue(this)">
<option value="10">Cotton</option>
<option value="20">Wet Look</option>
<option value="30">Crocodile</option>
</select>

Laravel - Drop down list where statement

I currently have a single drop down list that when i select the value it will display the data. However i am now adding in a new drop down list but when i press submit nothing is appearing.
I select distance and press submit data is presented. However, I have now included a price drop down list however nothing is appearing when i press submit. Can someone please help, see code:
SearchController.php
public function index(Request $request)
{
$distances = DB::table('posts')->select('distance')->distinct()->get()->pluck('distance');
$prices = DB::table('posts')->select('price')->distinct()->get()->pluck('price');
$postsInRange = $request->has('distance')
? Post::where('distance', $request->distance)->get()
: [];
return view('Pages.search', [
'distances' => $distances,
'prices' => $prices,
'posts' => $postsInRange
]);
Search.php
<div class="form-group">
<select name="distance" id="distance" class="form-control input-lg dynamic"
data-dependent="state">
<option value="">Distance</option>
#foreach($distances as $distance)
<option value="{{ $distance }}">{{ $distance }}</option>
#endforeach
</select>
<br>
<select name="price" id="price" class="form-control input-lg dynamic" data-
dependent="state">
<option value="">Price</option>
#foreach($prices as $price)
<option value="{{ $price}}">{{ $price}}</option>
#endforeach
</select>
Try this:
public function index(Request $request)
{
$distances = DB::table('posts')->select('distance')->distinct()->get()->pluck('distance');
$prices = DB::table('posts')->select('price')->distinct()->get()->pluck('price');
$postsInRange = $request->has('distance') ? Post::where('distance', $request->distance)->get()
: [];
$postsPrice = $request->has('price') ? Post::where('price', $request->price)->get()
: [];
return view('Pages.search', [
'distances' => $distances,
'prices' => $prices,
'posts' => $postsInRange,
'postsPrice' => $postsPrice
]);

Problems with Laravel Pivot Table

I am working on a medical lab application in laravel where I have the following tables:
1. Test table: This is a table which stores all the information related to medical tests:
2: Checkup: This is a page which contains all the patient information along with the tests he/she takes.
This is the test page:
This is the Checkup page where the tests and their results are selected:
Here can be many tests and user can check any number of them and will write the result of the test in the textfield below the checkbox.
I get this data in the controller like below code and save it to the database:
$this->validate($request,
[
'patient_name' => 'required|max:50',
'patient_age' => 'required',
'gender' => 'required',
'patient_type' => 'required',
'technition_id' => 'required',
'result' => 'required',
'test' => 'required',
'amount' => 'required'
]);
if( ($request->patient_type == 2) && ($request->doctor_id==0) )
{
return redirect()->back()->withInput(Input::all())->withErrors(['message' => 'Please select a valid Doctor.']);
}
$checkup = new Checkup;
$checkup->patient_name = $request->patient_name;
$checkup->patient_age = $request->patient_age;
$checkup->gender = $request->gender;
$checkup->patienttype_id = $request->patient_type;
$checkup->technition_id = $request->technition_id;
if(isset($request->doctor_id))
{
$checkup->doctor_id = $request->doctor_id;
}
$checkup->amount = $request->amount;
// $checkup->result = $request->result;
$checkup->save();
$tests =[];
$tests = $request->test;
$results =[];
$results = $request->result;
//$checkup->tests()->attach($tests->id, ['result' => $result]);
$sync_data = [];
for($i = 0; $i < count($tests); $i++)
$sync_data[$tests[$i]] = ['result' => $results[$i]];
$checkup->tests()->sync($sync_data);
Session::flash('success', 'The record was successfully saved.');
return redirect()->route('checkups.index');
Now the problem is that when I check all the checkboxes and write the result of all the tests then it is fine but when I select some and leave some of them then it gives error and the error comes because the result textbox for the unchecked test is empty.
This is the case when I select one test and leave the others:
When I check on test and write the result of it and then var_dump both test and result arrays i get the below output:
In the above image we can see that the test array contains one item because only one checkbox was checked but the result array contains two items and the first one is NULL which belongs to the unchecked checkbox.
This is the view file of the checkboxes and the textfields:
{{ Form::label('tests', 'Tests Taken') }}
#foreach(App\Test::all() as $test)
<div class="checkbox checkbox-switchery">
{{ Form::label('test', $test->name) }}
<input name="test[]" value="{{ $test->id }}" type="checkbox" class="switchery-primary">
</div>
<div>
{{ Form::label('result', "Result") }}
<input name="result[]" type="text" class="form-control">
</div>
#endforeach
<div class="form-group">
{{ Form::label('amount', 'Amount') }}
{{ Form::text('amount', null, ['class' => 'form-control']) }}
</div>
<div class="form-group">
{{Form::button('<i class="fa fa-save"> Save</i>', ['type' => 'submit', 'class' => 'btn btn-success'])}}
</div>
{!! Form::close() !!}
Please help me on this and show me how to insert the pivot table data properly to the system.
Thanks in advance for any help.
Try this..
In your blade file :
#foreach(App\Test::all() as $index => $test)
<div class="checkbox checkbox-switchery">
{{ Form::label('test', $test->name) }}
<input name="test[{{ $index }}]" value="{{ $test->id }}" type="checkbox" class="switchery-primary">
</div>
<div>
{{ Form::label('result', "Result") }}
<input name="result[{{ $index }}]" type="text" class="form-control">
</div>
#endforeach
Instead of the for loop you can use foreach lopp.
$sync_data = [];
foreach($tests as $index => $value) {
if(!empty($results[$index]) {
$sync_data[$value] = ['result' => $results[$index]]
}
}
$checkup->tests()->sync($sync_data);

Resources