I have problem with id increasing in laravel - laravel-5.5

I have the methods finishSave and numbers, when I call numbers from finishSave, and put dd() I took increasing id, so what about problem?
I tried dd($this->prefix_id); in PhoneNumber class Method numbers
protected function finishSave(array $options)
{
$this->numbers();
Cache::tags([config('app.env') . '_responsecache'])->flush();
parent::finishSave($options);
}
and numbers method
public function numbers()
{
dd($this->prefix_id);
}
I expect each time from DB the ID of prefix, but I took increasing id, and how I can get this I cannot understand, so help me

thank you all, occasionly it was my fault, I changed blade file from null to model than it was working, sorry.
I have done like this:
<div class="form-group">
{!! Form::label('region_id', 'Регион:', ['class' => 'text-semibold']) !!}
{!! Form::select('region_id', $regions, null, ['class'=>'form-control']) !!}
</div>
and changed to that:
<div class="form-group">
{!! Form::label('region_id', 'Регион:', ['class' => 'text-semibold']) !!}
{!! Form::select('region_id', $regions, isset($phoneNumber) ? $phoneNumber->phonePrefix->region_id : null, ['class'=>'form-control']) !!}
</div>

Related

Livewire: create and update in two tables

First to say that I am a newbie in Laravel. I have started to develop the frontend of an APP in Laravel Nova with Livewire. The problem is that before, I was able to do operations in my controller but I don't know how to do it in the Livewire resource.
I have a simple form:
<form wire:submit.prevent="submit" class="rounded px-8 pt-6 pb-8 mb-4">
<input type="text" placeholder="Introduzca código" wire:model="code" class="md:inline-block ktext-gray-700 text-sm font-bold mb-2">
<br>
#error('code')
{{$message}}
#enderror
<br>
<input type="text" placeholder="Introduzca tipo" wire:model="access" class="md:inline-block ktext-gray-700 text-sm font-bold mb-2">
<br>
#error('access')
{{$message}}
#enderror
<br><br>
<x-jet-button type="submit">Crear Asistencia</x-jet-button>
</form>
Which inserts three data into a table:
public function submit()
{
//validate
$this->validate();
Attendance::create([
'code' => $this->code,
'ip' => $_SERVER['REMOTE_ADDR'],
'access' => $this->access,
]);
But I want that in a second table, when the "code" field matches (it is in both tables and is a boolean) the code is update in this second table.
How would you do it? Thanks in advance.
Im not a pro laravel but a think any like the code below can help with yout question:
// If you have more than one register with same code:
$infos = SecondTableModel::where('code', $this->code)->get();
foreach ($infos as $info) {
SecondTableModel::find($info->id)->update([
'ip' => $_SERVER['REMOTE_ADDR'],
'access' => $this->access,
// ... OTHERS FIELSDS
]);
}
// If you have only one register on the second table with the same code
SecondTableModel::where('code', $this->code)->first()->update([
'ip' => $_SERVER['REMOTE_ADDR'],
'access' => $this->access,
// ... OTHERS FIELSDS
]);

Testing livewire component does not transfer variable to route() method

I'm testing my livewire component. In my component view I have a named route
route('add_result_bulk', ['round' => $round])
When I run the test, it gives this error:
Missing required parameter for [Route: add_results_bulk] [URI: results/add/{round}/bulk] [Missing parameter: round]. (View: /var/www/resources/views/results/livewire/add-results.blade.php) (View: /var/www/resources/views/results/livewire/add-results.blade.php)
If I put a #dd($round) right in front of the route() call, it dumps the $round variable.
Why is it not picking it up in the route then? My route is defined as:
Route::get('results/add/{round}/bulk', [ResultsController::class, 'bulk'])->name('add_results_bulk');
This is my test:
Livewire::test(AddResultsWrapper::class, ['round' => $round])
->set('results', [
[
"id" => null,
"name" => "",
"reserve" => null,
"clean" => false,
], [
"id" => null,
"name" => "Driver 2",
"reserve" => null,
"clean" => false,
],
])->call('validate')
->assertHasErrors(['results.0.name']);
}
$round is declared as a public property in my component. When I access the page through the browser, the link shows up and works correctly.
This is my view:
<div>
<form wire:submit.prevent="">
#csrf
<input type="hidden" name="form_type" value="single">
<div class="max-w-7xl mx-auto py-10">
<div class="bg-white overflow-hidden shadow-xl xl:rounded-lg overflow-x-auto">
<div class="p-6 pb-0 px-8 bg-white grid grid-cols-12 gap-x-4 gap-y-1 form-container min-w-1200px">
<div class="col-span-12">
<b>Please note:</b> When adding multi-lobby results, results need to be added using the <a
href="{{ route('add_results_bulk', ['round' => $round]) }}"
class="no-underline hover:underline text-blue-700">Bulk Loader</a>. Loading the results
here, will cause positions to be calculated incorrectly.
</div>
</div>
<div
class="p-6 px-8 bg-white border-b border-gray-200 grid grid-cols-12 gap-x-4 gap-y-1 form-container min-w-1200px">
...

Livewire checkbox preselected not working

I have collection of permission_types which i can access in my view. I am looping the permission_types to show each one in check box. all the checkboxes are binded to permission_resource, which is defined as a public property array. I want all the checkboxes to be preselected for which i used checked attribute but it won't work, as soon as i remove the wire:model attribute from input all the checkboxes are preselected. which narrows down the problem to wire:model binding.
What i am trying to achieve:
All i want to do is preselect the checkboxes binded to public property $permission_resource. Can anyone please help me out. I really cannot figure out what am i doing wrong here. Appreciate any effort to solve this problem in advance.
Relevent Component Code:
public $permission_types;
public $permission_resource = [];
public function render()
{
$this->permission_types = PermissionType::all();
// dd($this->permission_types->toArray());
return view('livewire.permissions.create-permission-component')
->extends('layouts.app')
->section('content');
}
Relevant View Code:
<div class="row">
#foreach($this->permission_types as $permissionType)
<div class="col-md-3">
<input wire:model="permission_resource" type="checkbox" class="filled-in chk-col-green form-control" id="{{$permissionType['name']}}" value="{{ $permissionType['name'] }}" checked />
<label for="{{ $permissionType['name'] }}" class="p-r-30">{{ ucfirst($permissionType['name']) }} Resource</label>
</div>
#endforeach
</div>
Permission Types Dump
What i have tried so far:
so far i have tried following but none of it worked for me.
1: defining public $permission_resource; instead of public $permission_resource = [];
2: wire:model="permission_resource.{{$permissionType["id"]}}"
3: wire:model="permission_resource.{{$permissionType["name"]}}"
4: wire:model.defer="permission_resource.{{$permissionType["id"]}}"
5: wire:model.defer="permission_resource.{{$permissionType["name"]}}"
6: name="permission_resource.{{$permissionType["id"]}}"
You are binding all the inputs to the same (array) variable, what you want to do is bind each to an element in that array, not to the array itself.
So you would need to prepopulate that array, and then bind each input using $loop->index.
Not sure if you have a good reason for populating permission_types in the render method, better in mount if it is not highly dynamic (likely to change from render to render).
Populating permission_resource in mount might look like this:
public function mount() {
$this->permission_types = PermissionType::all();
$this->permission_resource = $this->permission_types->pluck('name');
}
Then in the blade, bind to elements of the array, and don't set checked yourself, wire:model will always override this anyway, checking your checkbox if the thing you have bound to is truthy, and unchecking if bound var is falsey (this is why everything is unchecked for you with the wire:model binding them to the array, because empty($array) == false, if you just fix the casing of permission_type in the blade you will find the checkbox all come on when you check one, because they are all bound to the same thing).
<input wire:model="permission_resource.{{$loop->index}}" type="checkbox" class="filled-in chk-col-green form-control" id="{{$permission_type['name']}}" value="{{$permission_type['name']}}" />
PS: That will at least get to what you wanted, depending on what you are ultimately trying to do with permission_resource, it may not be a very good/useful representation for the purpose.
try this
public $permission = [];
protected $rules = [
...
'permission' => 'required|array',
];
public function create()
{
if ($this->validate()) {
$data = [
'name' => $this->name,
....
];
$model = Model::create($data);
if (!empty($this->permission)) {
$permissionId = PermissionType::whereIn('id', $this->permission)->pluck('id');
$model->permission()->attach($permissionId); // add name relation instead 'permission' , of create 'attach' of update 'sync'
}
}
}
public function render()
{
return view('livewire.permissions.create-permission-component', [
'permissions' => PermissionType::select('id', 'name')->get()
])
->extends('layouts.app')
->section('content');
}
in View
<div class="row">
#foreach($permissions as $permission)
<div class="col-md-3">
<input wire:model.defer="permission" wire:key="permission{{$permission->id}}" type="checkbox" value="{{$permission->id}}" class="filled-in chk-col-green form-control" />
<label for="{{ $permission->name }}" class="p-r-30">{{ ucfirst($permission->name) }} Resource</label>
</div>
#endforeach
</div>

How to hook event of validation error in livewire 2?

Reading how validations work at https://laravel-livewire.com/docs/2.x/input-validation
I did not find if there is a way in livewire 2 when I have
validation error to hook event as I need to send dispatchBrowserEvent event
to show message with toastr ?
My form is rather big and val;idation field can be out of screen
and I want to pay attention of user that there are validation errors...
Updated Block # 1:
You propose to get rid of livewire validate method and use laravel validate methods, which are written here
https://laravel.com/docs/8.x/validation, like :
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
...
In my conmponent I define all variables under 1 variable $form :
public $form
= [
'name' => '',
'state_id' => '',
...
public function firstStepSubmit()
{
$rules = [
'name' => 'required',
'state_id' => 'required',
];
$validation = Validator::make( $this->form, $rules, Hostel::getValidationMessagesArray());
$failed = $validation->fails();
if ($failed) {
$errorMsg = $validation->getMessageBag();
$focus_field = array_key_first($errorMsg->getMessages());
$this->dispatchBrowserEvent('PersonalPageMessageWarning', [
'title' => 'Personal Hostel',
'message' => 'Your hostel has invalid data !',
'focus_field' => str_replace('form.', '', $focus_field ),
]);
$validation->validate(); // What for this line ? Looks like we really need it ?
return;
}
$this->currentStep = 2;
} // public function firstStepSubmit()
// What for is
$validation->validate();
line inside of failed block ? Do we really need it ?
2) moving to laravel original methods sems for me as step back... Are there some livewire hooks/methods for it ?
Thanks in advance!
I got a solution to that. Let's say you have next:
// in blade
<div class="col-md-6 flex-row">
<label for="name">Name</label>
<input id="name" type="text" class="form-control flex-row" wire:model="name">
#error('name') <span class="error" style="color: #ff0000">{{ $message }}</span> #enderror
</div>
<div class="col-md-6 flex-row">
<label for="last_name">Name</label>
<input id="last_name" type="text" class="form-control flex-row" wire:model="last_name">
#error('last_name') <span class="error" style="color: #ff0000">{{ $message }}</span> #enderror
</div>
.... // all the rest of elements
//in component
public $name, $last_name;
// the rest of properies
public function store()
{
$validation = Validator::make([
'name' => $this->name,
'last_name' => $this->last_name,
.....
], $this->rules());
if ($validation->fails()) {
$errorMsg = $validation->getMessageBag();
$this->dispatchBrowserEvent('focusErrorInput',['field' => array_key_first($errorMsg->getMessages())]);
$validation->validate();
}
//... other code
now, if validation fails, the above validation checks dispatch and event with all the non-validated fields and in the blade's script tag handle the element focus in order of the error bag field. So, if the element is out of windows this will be focused
<script>
window.addEventListener('focusErrorInput', event => {
var $field = '#' + event.detail.field;
$($field).focus()
})
</script>

Call typescript function from onclick

I created a SharePoint Framework Webpart.
I call a webservice that returns some data from sharepoint (terms from termstore), and for each term i generate an html that display the term. On the onclick of each term i want to call a typescript function, passing the term as parameters, to get its children terms.
This code below create the following wrong behaviour: when the webpart is displayed, it automatically calls the function this.readIterm when I didnt even click on it !
Am I missing something or by design doing it the wrong way ? I tried to replace onclick="${this.readIterm(term)}" by onclick="readIterm($(term))" but it does nothing.
Code below
terms.forEach(term => {
htmlContent +=
`<div class="w3-card w3-third w3-margin-bottom" style="" onclick="${this.readIterm(term)}">
<header class="w3-container w3-blue">
<h1>Header</h1>
</header>
<div class="w3-container">
<span>${term.name}</p>
</div>
<footer class="w3-container w3-blue">
<h5>Footer</h5>
</footer>
</div>`
This html is then added to this.domElement.innerHTML, displaying it in the webpart.
public readIterm(myTerm: ITerm) {
alert("readIterm is clicked");
}
Thank you in advance for your help and guidance if I do not follow best practice !
Jeff
There is one more way to attach event listener.
Refer below code sample. This works perfectly for me:
(Note: This is a basic idea. You can refer this code and make changes to yours accordingly.)
public render(): void{
this.domElement.innerHTML = ` <div class="form-group">
<button class="btn btn-success" id="btnReadAllItems">
<span class="ms-Button-label">Read All Items</span>
</button>
<button class="btn btn-success" id="btnReadItemById">
<span class="ms-Button-label">Read Item By Id</span>
</button>
</div>`;
this._setButtonEventHandlers();
}
private _setButtonEventHandlers(): void {
const webPart: SpfxCrudWebPart = this;
this.domElement.querySelector('#btnReadAllItems').addEventListener('click', () => {
this._GetListItemsNF();
});
}
private _GetListItemsNF(): void {
//
//
//
}
Another way is as below. (But you will have to make some changes according to your code)
public render(): void{
htmlContent +=
`<div class="w3-card w3-third w3-margin-bottom" id="test">
<header class="w3-container w3-blue">
<h1>Header</h1>
</header>
<div class="w3-container">
<span>${term.name}</p>
</div>
<footer class="w3-container w3-blue">
<h5>Footer</h5>
</footer>
</div>`
}
this._setButtonEventHandlers();
this.myTerm = term; // Here we are assigning value to the `myTerm` variable. And `myTerm` is a public property, So value of `myTerm` will be accessible using `this.myTerm`
}
public myTerm: ITerm; // here we are declaring `myTerm` variable
public readIterm():void{
// here you can access the cariable `myTerm` using `this.myTerm`.
// alert(this.myTerm);
// alert("readIterm is clicked");
}
private _setButtonEventHandlers(): void {
this.domElement.querySelector('#test').addEventListener('click', () => { this.readIterm(); });
}
Rather onClick instead of onclick. Then check to make sure that you get into your "readIterm" method by calling the console (console.log).