jQuery select2 dynamic options - javascript

I have a multiselect that I want to use as a search box so that the user can search by category, event type, location and keywords. It has the following structure:
<select name="search-term[]" multiple="multiple">
<optgroup label="Categories">
<option value="category_4">Internal</option>
<option value="category_2">Business</option>
<option value="category_5">External</option>
<option value="category_1">Science</option>
<option value="category_6">Sports and Social</option>
</optgroup>
<optgroup label="Event Types">
<option value="eventtype_2">Meeting</option>
<option value="eventtype_3">Social Activity</option>
<option value="eventtype_4">Sporting Activity</option>
<option value="eventtype_1">Symposium</option>
</optgroup>
<optgroup label="Locations">
<option value="location_2">Office 1</option>
<option value="location_3">Office 2</option>
<option value="location_1">Office 3</option>
</optgroup>
</select>
I have initialised select2 with the tags option set to true so like so:
$('select').select2({
tags : true,
createTag: function (params)
{
return {
id: 'keyword_' + params.term,
text: params.term,
newOption: true
}
}
});
This allows users to enter a new option if it doesn't exist and takes care of the keywords requirement. Any new tags are appended with keyword_ so that the server knows how to handle them when the form is submitted.
This is all working as I expected however the issue I've come across is if someone wants to search for a keyword that is called the same as one of the other options then they aren't able to create a new keyword tag it will only let them select the existing option. For example if I search Office 1 I may want to search for events that are located at office 1 or I may want to do a keyword search so that I am searching for events that have office 1 in the title. The problem is currently I'm only able to select the location option I'm not able to create a new tag. Does anyone know how I could achieve this?

I achieved this in the end by using an AJAX datasource which gives you much more control over what options are shown to the user. Here is my code:
$('select').select2({
ajax: {
url: "/server.php",
dataType: 'json',
type: "GET",
delay: 0,
data: function (params) {
var queryParameters = {
term: params.term
}
return queryParameters;
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.text,
id: item.id,
children: item.children
}
})
};
},
cache: false
},
templateSelection: function(item)
{
return item.parent+': '+item.text;
}
});
Contents of server.php:
<?php
$term = !isset($_GET['term']) ? null : ucfirst($_GET['term']);
$categories = array('Meeting', 'Seminar', 'Sports and Social');
$locations = array('Cambridge', 'London', 'Northwich');
$matching_categories = array();
$matching_locations = array();
foreach($categories as $i => $cat) {
if(is_null($term) || stripos($cat, $term)!==false) {
$matching_categories[] = array(
'id' => 'category_'.$i,
'text' => $cat,
'parent' => 'Category'
);
}
}
foreach($locations as $i => $loc) {
if(is_null($term) || stripos($loc, $term)!==false) {
$matching_locations[] = array(
'id' => 'location_'.$i,
'text' => $loc,
'parent' => 'Location'
);
}
}
$options = array();
if(!empty($matching_categories)) {
$options[] = array(
'text' => 'Category',
'children' => $matching_categories
);
}
if(!empty($matching_locations)) {
$options[] = array(
'text' => 'Location',
'children' => $matching_locations
);
}
if(!is_null($term)) {
$options[] = array(
'text' => 'Keyword',
'children' => array(
array(
'id' => 'keyword_'.$term,
'text' => $term,
'parent' => 'Keyword'
)
)
);
}
echo json_encode($options);

Related

How can I add data-icon attribute dynamically with vanilla JS on the options of a select in a Grid JS table?

I added a dropdown select to a Grid Js table to filter some rows and it works just perfectly, but I want to add some icons to the option tag in that select dropdown using data-icon attribute like this: Cruise Line. The icon library is already set on my page and works fine (I know that because I can display the icons somewhere else on the page). I'm adding the data-icon when creating the select with js (vanilla, no jquery), and I can see in the page source that the attribute is added, but is not displaying anything. Any help is greatly appreciated. Thank you
if (document.getElementById("table-search")) {
const gridtab = new gridjs.Grid({
columns: [{
name: 'Class',
width: '100px',
formatter: (function (cell) {
return gridjs.html('<span class="fw-semibold d-flex justify-content-center align-items-center"><h4><i class="' + cell + ' text-info"></i></h4></span>');
})
},
{
name: 'OL/PU',
width: '120px',
formatter: (function (cell) {
return gridjs.html('<span class="fw-semibold d-flex justify-content-center align-items-center"><h5><i class="' + cell + ' text-danger"></i></h5></span>');
})
},
"Name",
"City",
{
name: 'Actions',
width: '120px',
formatter: (function (cell) {
return gridjs.html('<h5><i class="ri-zoom-in-line text-muted"></i></h5>');
})
},
],
pagination: {limit: 25},
search: true,
sort: true,
resizable: true,
server: {
url: 'dir_pick_ups_fetch.php?cla=0',
then: data => data.map(obj => [obj.htl_classif_icon,obj.olspot,obj.hotel_name, obj.city])
},
style: {
th: {
'font-size': '13px'
},
td: {
'font-size': '13px',
'color':'#878a99'
}
}
}).render(document.getElementById("table-search"));
/* insert search select field */
function insertButtonToTableHeader() {
const select_wrapper = document.createElement('div')
select_wrapper.className = 'float-end';
function insertButtonToButtonWrapper(buttonName) {
<?php
$output ='{valor:"0", txt:"All Cities"},';
$stmt = $db->prepare('SELECT city_id, city_name, city_state FROM dir_canada_cities ORDER BY city_name');
$stmt->execute();
while ($rrows = $stmt->fetch(PDO::FETCH_ASSOC)) {
$output .= '{valor:"' . trim($rrows['city_name']) . '", txt:"' . $rrows['city_name'] . ', ' . $rrows['city_state'] . '"},';
}
$output = rtrim($output, ", ");
?>
var values = [<?php echo $output; ?>];
var select = document.createElement("select");
select.name = "classification";
select.id = "classification";
select.className = "form-select";
for (const val of values) {
var option = document.createElement("option");
option.value = val.valor;
option.text = val.txt;
select.appendChild(option);
}
select_wrapper.appendChild(select);
}
insertButtonToButtonWrapper('Insert')
const grid_js_head = document.querySelector('.gridjs-head')
const gridjs_search = document.querySelector('.gridjs-search')
grid_js_head.insertBefore(select_wrapper, gridjs_search)
/* filter display selection */
document.getElementById('classification').addEventListener('change', function() {
var newsort = this.value;
gridtab.updateConfig({
server: {
url: 'dir_pick_ups_fetch.php?cla=' + newsort,
then: data => data.map(obj => [obj.htl_classif_icon,obj.olspot,obj.hotel_name, obj.city])
},
}).forceRender();
insertButtonToTableHeader()
document.getElementById('classification').value = newsort;
console.log('You selected: ', this.value);
})
}
insertButtonToTableHeader()
}
The source code shows the data-icon is added, but no icons are displayed in the dropdown:
<select name="classification" id="classification" class="form-select">
<option value="1" **data-icon="ri-ticket-line"**>Attractions</option>
<option value="9" **data-icon="ri-ship-line"**>Cruise Line</option>
<option value="11" **data-icon="ri-basketball-line"**>Events</option>
<option value="7" **data-icon="ri-user-star-line"**>Guides - Freelance</option>
<option value="10" **data-icon="ri-moon-line">Night Clubs**</option>
</select>
I'm using bootstrap 5.1.3

Laravel 7 - Trouble retrieving old value of dynamic select when validation fails

The form has a select for Customer with populates from a variable in the controller. I can easily retrieve the old input value using old('customer_id').
My problem comes from the second select. The second select uses javascript to populate the Customer Contact based on which Customer is chosen. When validation fails, I lose that value.
Here is the controller code for the store method:
$rules = [
'number' => 'required',
'customer_id' => 'required',
'contact_id' => 'required',
'payment_type' => 'nullable',
'department_id' => 'required',
'requested_ship_date' => 'required|after:yesterday',
];
$customMessages = [
'number.required' => 'The Sales Order number is required.',
'customer_id.required' => 'Please choose a customer.',
'contact_id.required' => 'Please choose a contact.',
'requested_ship_date.required' => 'You must enter a ship date.',
'requested_ship_date.yesterday' => 'The requested ship date must be today or after.',
'department_id.required' => 'Please choose a department.'
];
$salesorder = \request()->validate($rules, $customMessages);
SalesOrder::create($salesorder);
return redirect('/salesorders');
Here is Customer Select:
<select
name="customer_id"
class="shadow text-sm">
#if (old('customer_id'))
<option
value>
</option>
#else
<option
selected
value>
</option>
#endif
#foreach($customers as $customer)
#if (old('customer_id'))
<option
value="{{ $customer->id }}" {{ old('customer_id') == $customer->id ? 'selected' : '' }}>
{{ ucfirst($customer->name) }}
</option>
#else
<option
value="{{ $customer->id }}">
{{ ucfirst($customer->name) }}
</option>
#endif
#endforeach
</select>
Here is the select for the Customer Contact:
<select
name="contact_id"
class="shadow text-sm text-center"
>
<option>
</option>
</select>
And here is the javascript:
$('select[name="customer_id"]').on('change', function () {
var customerId = $(this).val();
if (customerId) {
$.ajax({
url: '/customer/contacts/get/' + customerId,
type: "GET",
dataType: "json",
beforeSend: function () {
$('#loader').css("visibility", "visible");
},
success: function (data) {
$('input[name="email"]').val('');
$('select[name="contact_id"]').empty();
$('select[name="contact_id"]').append('<option value="Choose">Choose Contact</option>');
$.each(data, function (key, value) {
$('select[name="contact_id"]').append('<option value="' + key + '">' + value + '</option>');
});
},
complete: function () {
$('#loader').css("visibility", "hidden");
}
});
} else {
$('select[name="customer_id"]').empty();
}
});

Html::dropDownList depending Yii2

I have a problem to connect two select. I would like the choice of a select filters the search of the second select statement.Both select take data from their tableDB but are not influenced each other. Can someone help me?
my first select customers take data from db table customers:
<?=
Html::dropDownList('userlist', [],
ArrayHelper::map(Customers::find()->where('id',['company_id' =>
'name'])->orderBy('name')->all(), 'id', 'name'),
['prompt' => 'Select a User ...',
'class' => 'form-control',
'style' => 'width: 100%;']);
?>
my second select offers take data from db table offers:
<?=
Html::dropDownList('offerslist', [],
ArrayHelper::map(Offers::find()->where('customer_id',['company_id'
=> 'offers_n'])->orderBy('customer_id')->all(),
'id','offers_n','customer_id'),
['prompt' => 'Select a Offert ...',
'onchange' => 'change_user_list(this.value)',
'class' => 'form-control',
'style' => 'width: 100%;']);
?>
This is my function js:
function change_user_list(company_id)
{
$.ajax({
url: "<?= \yii\helpers\Url::to(['offers/userlist'])?>",
type: 'get',
data: {
company_id: company_id
},
success: function (data) {
document.getElementsByName('userlist')[0].innerHTML = data;
}
});
}
this is my actionFucntion in the controller:
public function actionUserlist($company_id)
{
if (Yii::$app->request->isAjax) {
$userlist = ArrayHelper::map(Customers::find()-
>where(['company_id' => $company_id])->orderBy('name')->all(),
'id', 'name');
$string = "<option value>Select a Users</option>";
foreach($userlist as $id => $name) {
$string .= "<option value=".$id.">".$name."</option>";
}
return $string;
}
}

Pass javascript value to a form action URL in Yii2

I'm trying to put a value from javascript into a form action in Yii2
is it possible?
More specifically I need to make a URL change for each option that is selected in a dropdownList.
form in views/site.php
$form = ActiveForm::begin([
'id' => 'form',
'method' => 'POST',
'action' => Url::to(['programas/'.Tours::findOne(['pk' => ])->programa]),
]);
<?= $form->field(new \app\models\Tours(), 'nombre')->dropDownList([],
[
'prompt' => 'Programa',
'id' => 'child1_child2',
'onchange' => 'updateValue(this.value)',
]
)->label(false); ?>
Js file
function updateValue(val){
x = document.getElementById("test").value;
// document.getElementById("form").action = "programas/";
}
So, I rescue the value from the selected option with JS but I need to put it in here 'pk' => 'value'
where value is the #child1_child2 selected option value.
'action' => Url::to(['programas/'.Tours::findOne(['pk' => ])->programa])
Thanks for the help.
You can use one of the following approach with some modification:
//pk => programa
$data = [
1 => 'programa1',
2 => 'programa2',
3 => 'programa3',
];
1) Use JS
<?= $form->field(new \app\models\Tours(), 'nombre')->dropDownList($data, ['prompt' => 'Programa'])->label(false); ?>
JS
$this->registerJs('
$("#dropdownID").change(function() {
var text = $("#dropdownID option:selected").text();
$("#formID").attr("action", "/pathtoproject/programas/" + text);
});
', \yii\web\View::POS_END);
2) Use Ajax Call
<?= $form->field(new \app\models\Tours(), 'nombre')->dropDownList($data, [
'prompt' => 'Programa',
'onchange'=> '$.get( "'.Url::toRoute('get-action').'", { id: $(this).val() } )
.done(function( data ) {
$("#formID").attr("action", data);
}
);'
])->label(false); ?>
Controller
public function actionGetAction($id)
{
$name = Tours::findOne(['pk' => $id])->programa];
echo \yii\helpers\Url::to(['programas/'.$name]);
}

want to select user from onchange of dropdown list of department in cakephp?

i have two tables user and department where department has two fields id and name i want to create a view so that when someone selects a department name from the dropdownlist the user's name of all in that department show in another dropdownlist using AJAX and How to call that in controller
<script>
jQuery(document).ready(function ($) {
//jQuery('#searchTable').dataTable();
$('#department_id').change(function () {
jQuery('#user').empty();
var data2 = {};
data2['department_id'] = jQuery(this).val();
var json = JSON.stringify(data2);
jQuery.ajax({
type: "POST",
url: "/AjaxRequests/name",
data: json,
dataType: "json",
success: function (response) {
var app = "<option value>All</option>";
jQuery('#user').append(app);
jQuery.each(response, function (i, text) {
jQuery('#user').append(jQuery('<option></option>').val(i).html(text));
});
}
});
});
</script>
this is the script i am using
and in view the department dropdown is like this
<?php echo $this->Form->input('department_id', array('onChange' => 'showFields(this.value)', 'class' => 'form-control-custom', 'id' => 'department_id', 'type' => 'select', 'label' => true, 'label' => 'department:', 'options' => $departments, 'empty' => 'Select A Department', 'required' => 'false'))
?>
Anyone please help me with this ajax and also the controller
According to your code, can u try to replace 'id' => 'department' with 'id' => 'department_id' . Cause it's seen here you are using department_id as selector but your department_id id as not declared in dropdownlist. Here you declared department as ID. So selector is not found. So Just replace 'id' => 'department' with ''id' => 'department_id'', Hope it can be helpful to you.

Categories