Laravel Select2 old input after validation Laravel Select2 old input after validation ajax ajax

Laravel Select2 old input after validation


Normally to programmatically set the value of a select2, you would expect to use the .val() method followed by a .trigger('change') call as per their documentation (and other queries like this on SO). However, select2 themselves have something in their documentation about preselecting options for remotely sourced data.

Essentially their suggestion boils down to (after initalizing your AJAX-driven <select>):

  • make another AJAX call to a new API endpoint using the pre-selected ID
  • dynamically create a new option and append to the underlying <select> from a promise function (.then()) after the AJAX call is finished
    • could also use some of the regular jQuery callback chaining functions for this
  • trigger a change event
  • trigger a select2:select event (and pass along the whole data object)

Assuming you're already flashing the old data to the session, Laravel provides handy access to the previously requested input in a variety of ways, notably these three:

  • static access via the Request class e.g. Request::old('customer') as in the OP
  • the global old() helper e.g. old('customer'), which returns null if no old input for the given field exists, and can have a default as a second parameter
  • using the old() method on the Request instance from the controller e.g. $request->old('customer')

The global helper method is more commonly suggested for use inside Blade templates as in some of the other answers here, and is useful when you don't need to manipulate the value and can just plug it straight back in, which you would with things like text inputs.

The last method probably provides you with the answer you're looking for - instead of querying the entire collection from inside of the view, you're able to either manipulate the collection from the controller (similar to the OP, but should be nicer since it's not parsing it in the view) or make another query from the controller based on the old ID and fetch the data you want without having to trawl the collection (less overhead):

$old_customer = Customer::find($request->old('customer'));

Either way, you'd have the specific data available at your fingertips (as a view variable) before the blade template processes anything.

However you choose to inject the data, it would still follow the pattern suggested by select2:

  • get the pre-selected data
  • create an option for it
  • trigger the appropriate events

The only difference being you don't need to fetch the data from another API endpoint (unless you want/need to for other programmatic reasons).


I end up using similar flow like your. But my blade template is using htmlcollection package.

Controller:-

Let's say you are in create() method. When validation failed, it will redirect back to the create page. From this page, you can repopulate the list.

$customer_list = [];if(old('customer') != NULL){    $customer_list = [old('customer') => $customers->where('id', old('customer'))->first()->name];        }

Blade View:

{{ Form::select('customer', $customer_list, null,  ['class' => 'searchselect searchselectstyle', 'id' => 'customer']) }}


Maybe you can try (once the ajax call has ended) :

var oldCustomer = $('#customer > option[value={{ Request::old('customer') }}]');if (oldCustomer.length > 0) {    oldCustomer.attr('selected', 'selected');}