Keeping select values across pages - ajax

I have a couple of routes
Route::get('/route_one', 'IndexController#index');
Route::get('/route_two', 'IndexController#index');
They call the same controller function because these pages need the same array of data. This function is as follows
public function index()
{
$user = Auth::user();
if( $user ) {
$fileData = $this->fillArrayWithFileNodes(new DirectoryIterator( public_path(). '/images'));
$currentPath= Route::getFacadeRoot()->current()->uri();
if(!empty($fileData)) {
return view('index', compact('fileData', 'currentPath'));
}
} else {
return view('auth.login');
}
}
Now the index view is pretty straight forward, but it does has this part
#if($currentPath == 'route_one')
#include('layouts.searchbarRouteOne')
#endif
#if($currentPath == 'route_two')
#include('layouts.searchbarRouteTwo')
#endif
So depending on what route is called, a different sidebar is displayed. Now the sidebars essentially contain a load of select inputs like the following
<div class="col-lg-3">
<div class="form-group">
<label>Year</label>
<select id="year" class="form-control">
<option value=""></option>
#foreach($fileData["route_one"] as $year => $products)
<option value="{{ $year }}">{{ $year }}</option>
#endforeach
</select>
</div>
</div>
Both sidebars have different selects. When select options are selected, an ajax call is made to display an image. This all works fine.
This is my problem. I have a link to get to route_one or route_two. As the page refreshes when the link is clicked, the selects are at their default state. What I would like to do somehow is keep the last state of the select inputs. I am not storing this data within a database which may be an issue?
Furthermore, route_two relies on the select options from route_one. So when route_two is selected, I need to pass it route_ones options.
What would be the best way to achieve what I am after?
Thanks

Think what you are trying to accomplish here: remember the old input values.
You could send the form when clicking the link and flash the data in your controller or use JavaScript saving input values to the browser's storage.
Simple example using plain JavaScript
// Get all select-elements
var inputs = document.querySelectorAll('select');
// Loop through them
for (var i = 0; i < inputs.length; i++) {
// Set the old input value
inputs[i].value = localStorage.getItem(inputs[i].name);
// Start listening changes
inputs[i].addEventListener('change', store);
}
// The function to call when the value has changed
function store(event) {
// Set the new value to the browser's storage
localStorage.setItem(event.target.name, event.target.value);
}
In that example your form elements are required to have unique name attributes. Of course it can be switched out using e.g. id attribute.

Related

I am stuck in Laravel Livewire in which I am using multiple select2 and it is a wizard form

I have a wizard in laravel livwire with 4 steps.
in the first step I have select box of select2 for multiple selection, everything works fine but when I go to step 2 and return back, the problems comes
Select2 distorts and loose it's styling
Selectbox does not contain it's selected values
I am new to livwire so do not enough about it.
Here is my blade component
I don't exactly know what is the purpose of wire:ignore but I used it from internet.
<div class="col-sm-12 col-md-6 col-xl-6 col-lg-6 mb-10">
<x-label for="vehicle_groups" class="required">Vehicle Groups</x-label>
<div wire:ignore>
<x-select-two class="form-select-solid" id="vehicle_groups" multiple>
<option value=""></option>
#foreach($vehicleGroups as $vehicleGroup)
<option value="{{ $vehicleGroup->id }}">{{ $vehicleGroup->group_name }}</option>
#endforeach
</x-select-two>
</div>
#error('vehicle_groups')
<x-error>{{ $message }}</x-error>
#enderror
</div>
<script>
document.addEventListener("livewire:load", () => {
$('#vehicle_groups').select2().on('change', function (e) {
var data = $('#vehicle_groups').select2("val");
#this.set('vehicle_groups', data);
});
});
</script>
here is my livewire component
<?php
namespace App\Http\Livewire;
use App\Models\Vgroup;
use Livewire\Component;
class Vehicle extends Component
{
public $currentPage = 1;
public $type, $vehicle_groups;
public function mount()
{
}
public function render()
{
$vehicleGroups = Vgroup::get(['id', 'group_name']);
return view('admin.livewire.vehicle', compact('vehicleGroups'));
}
public function gotToNextPage()
{
if ($this->currentPage === 1) {
$this->validate([
'type' => ['required'],
'vehicle_groups' => ['required']
]);
} elseif ($this->currentPage === 2) {
} else {
}
$this->currentPage++;
}
public function gotToPreviousPage()
{
$this->currentPage--;
}
public function submitForm()
{
$this->currentPage = 1;
}
}
wire:ignore you will use it, if you don't want to rerender a part of your code, for example imagine you have a js code, and when using it with livewire it can not work well, because livewire makes requests every time and the js code can't do it's job, now, you have to know that select2, creates it's own DOM and livewire keeps making requests(so you can see it's not a good combination), for that reason you need to add wire:ignore(to ignore select2).
So the problem that the styles doesn't render again, you could try adding the select 2 inside a DOMContentLoaded event:
document.addEventListener("DOMContentLoaded", () => {
$('#vehicle_groups').select2();
})
like this, the styles will be added when the page is loaded
on the other side, to get the data, you could try and add the ready event:
$(document).ready(function() {
$('#vehicle_groups').select2("val");
})
or
$(document).ready(function() {
$('#vehicle_groups').select2();
$('#vehicle_groups').val();
})
I see that you are using an event "livewire:load", in my case this event didn't work for me(in the inspector it throw me an error that the event didn't exist), you could try and use a hook instead of "livewire:load"
Livewire.hook('message.processed', (message, component) => {
})
this event will be called when all the requests of livewire are finished
https://laravel-livewire.com/docs/2.x/lifecycle-hooks
here is the link to the documentation if you want to check it
And last i want to comment something, i saw that you are using $vehicleGroup (i guess it's an array), you are getting the data on the view, all okei there, however you using the array on select 2, to overrite the data, is that what you want to do?(#this.set('vehicle_groups', data))
you could use the attribute wire:model(if you don't need to make requests every time in that select better use wire:model.defer, like this the only request that is going to make is when it's submited), to call a variable on livewire and store the value of the select
<x-select-two class="form-select-solid" wire:model="vehicle_variable" id="vehicle_groups" multiple>
<option value=""></option>
#foreach($vehicleGroups as $vehicleGroup)
<option value="{{ $vehicleGroup->id }}">
{{$vehicleGroup->group_name }}
</option>
#endforeach
</x-select-two>
wire:model="vehicle_variable"
now on livewire:
public $vehicle_variable
and on select2:
#this.set('vehicle_variable', data)
now you have the value on a variable and not an array(if it's an array)
to check if the data exists, you could use the debugger of laravel "ddd()" inside the function mount (the mount function, will be called when the page is being loaded):
public function mount()
{
ddd($vehicle_variable);
}
if it's not null, then select2 should work however, if the value is null you need to check your livewire
if you have any question, just ask and i will try to answer!

Laravel 8 multi value select filtering

I'm trying to build Laravel project that will have a multi-select dropdown with list of categories. Selecting category should reload the page and apply filter.
"scopeFilter" in my model is actually doing filtering, but here i just need to find a way to properly form URL. The problem is that this code i have:
<form id="cats-form" action="#" method="GET">
<select multiple class="chosen-select" name="test[]">
#foreach($categories->get() as $cat) //this loop goes through existing categories in the system
#php
//if category is part of URL, pre-select it in the select:
$arr = request()->all();
$selected = '';
if(array_key_exists('test', $arr)) {
$testArr = $arr['test'];
$selected = in_array($cat->id, explode(',', $testArr)) ? 'selected' : '';
}
#endphp
<option {{ $selected }} value="{{ $cat->id }}">{{ $cat->name }}</option>
#endforeach
</select>
</form>
<script>
$(".chosen-select").chosen({ })
$('.chosen-select').on('change', function(evt, params) {
$('#cats-form').submit();
});
</script>
Is actually giving me this URL:
http://localhost:11089/?test%5B%5D=19&test%5B%5D=5
While i actually need this:
http://localhost:11089/?test=19,5
I guess it's a trivial problem to solve for someone with better knowledge of Laravel, can you tell me pls what i'm doing wrong here?
This is rather how the language or framework or library reads an URL query string. Assuming that your prefered way of URL string is a valid format (as I usually see the format ?arr[]=val1&arr[]=val2 and never see the second format that you preferred), both query string formats should be acceptable to PHP.
As Yarin stated that the best way PHP reads an array is the first method, you don't have to worry too much because the decoded URL query string is exactly in the first format.

How do I return an option saved to the Laravel database?

I am programming a system in Laravel 5.8 and nenessito do the editing of the user through a select but when I make the request does not appear the option that the user selected.
I already tried to pass the Controller attractive but not right.
public function edit($id)
{
$users = User::find($id);
$institutions = Institution::all('razaosocial');
return view('users.edit', compact(array('users','institutions')));
}
<div class="form-row">
<div class="col-md-6">
{{Form::label('Instituição:')}}
<select class=form-control name="instituicao" id="instituicao">
<option value="null">Selecione uma Instituição</option>
#foreach($institutions as $institution)
<option value="{{$institution->razaosocial}}">
{{ $institution->razaosocial}}
</option>
#endforeach
</select>
</div>
</div>
I hope that appears in the view the option selects by during registration.
Hoping something works in programming is very frustrating and I am at the moment. compact() actually creates an associative array whose keys are variable names and their corresponding values are array values. So instead of
compact(array('users','institutions'));
make it
compact('users','institutions');
Here is a reference that solves this problem
Laravel: Display data in DropDown from database

How to get array value that get from checkbox input in Laravel's controller?

I want to send 'Date' array from a page to another page through checkbox input for display the data and get more data from database.
I try to dd() the array from input, it's still normal but the data just only show 1 value when I use 'foreach' loop. How do I do?
<input name="isInvoices[]" type="checkbox" value="{{ $date }}">
$invoices = $request->input('isInvoices');
// dd($invoice); It's show array of date
foreach($invoices as $invoice) {
dd($invoice); //It's just only 1 value
}
I expected the output to show all value in the array, but the actual output is show 1 value.
dd means dump and die. Which after the first iteration stops, that's why you see only one item. Try this:
foreach($invoices as $invoice) {
dump($invoice);
}
die;
before such would function, you have to have series of checkbox like:
this is display series of date values on checkbox. so when you select any dates and submit
foreach($datevalue as $date){
<input name="isInvoices[]" type="checkbox" value="{{ $date }}">
}
//this gets the date value
$invoices = $request->input('isInvoices');
//this will display all the selected checkboxes
foreach($invoices as $invoice) {
dd($invoice);
}
dd() – stands for “Dump and Die”, and it means as soon as loop gets to this command, it will stop executing the program, in this case in first interation. To display all data in foreach loop, use echo or print_r():
foreach($invoices as $invoice) {
echo $invoice;
}
This means that the program will print $invoice for each iteration. Then you can access your data like this:
$invoice['value']
You can read more about different types of echoing here.

Ordered selection from a dropdown

I want to create an ordered list from a multiple select dropdown list, issue is the select option input provided by html only orders values picked linearly, but I want it ordered according to the order I select them at. So I decided to use some JS to do the trick but wsnt able to hack. Here's the code. Help out please!!
<script language="'javascript'">
function showselection()
{
var frm = document.testing
var opt = frm.testsel
var numofoptions = opt.length
var selValue = new Array
var j = 0
for (i=0; i<numofoptions; i++)
{
if (opt[i].selected === true)
{
selValue[j] = opt[i].value
j++
}
}
selValue = selValue.join("+")
document.getElementById("txtEditions").innerHTML = selValue
}
</script>
<form method=POST name='testing'>
<select name='testsel' multiple onchange='showselection()'>
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
<textarea id="txtEditions"></textarea>
</form>
how do i make sure the order of selection is saved and not the order from the source of the dropdown
Codeigniter has a form helper for form_dropdown / form_multiselect this allows you pass an array to the helper function to create the html. you can order the array before parsing it to this function with an array sorting function, like ksort or asort depending on your data.
sorry I can't be of more help because I am not clear exactly what you need to do. if you literally want to save the order, then that means saving it in a database structure in some way.

Resources