Dynamic select2 options using api - javascript

I'll try to explain my problem as much as I can. I am trying to create, with select2 plugin, a way for the user to write some letters and on each letter pressed a call to an API that gives the first 20 results given by that API.
So I have my HTML select :
<select name="filtre_products[]" class="form-control products-select2" multiple>
</select>
And then my JS (it's commented) :
$(".products-select2").select2({
width: '100%',
closeOnSelect: false,
placeholder: '',
minimumInputLength: 3,
query: function (query) {
var data = {results: []}, i, j, s;
if(query.term != null) {
var ajax_r = [];
$.ajax({
url: 'ajax_products_recherche.php?limite=10&real_json=1&recherche='+query.term,
success: function(data_a){
//Getting the data
data_a = JSON.parse(data_a);
//Looping through the each data and putting them inside a table
data_a.forEach( (e) => {
ajax_r.push(e);
});
//Filtering the data to get from it the id and the text to be used
ajax_r.forEach( (e) => {
var tmp = e.split('-');
var id = tmp[0];
var name = tmp[2];
data.results.push({value: id, text: name});
});
query.callback(data);
}
});
}
},
//Sending the results to the function to modify the options as I please
templateResult: formatResult
});
And this is the formatResult function I use :
function formatResult(d) {
if(d.loading) {
return d.text;
}
// Creating an option of each id and text
$d = $('<option/>').attr({ 'value': d.value }).text(d.text);
return $d;
}
My problem is that select2 is supposed to be creating the options dynamically upon initialization and thus actually creating <li> out of the options and adding to them dynamically id's and such. But in the way I'm creating it, it's putting the options INSIDE the <li> tags which is not what I want, I want it to treat it as dynamic options like he does without the query call.
Some doc sources for you guys, it shows a part of what I'm trying to do, but the example shows how to show results from what we write, I want it to show from the api upon each click, and of course having multiple select added :
http://select2.github.io/select2/#data

I've read the documentation and found that the ajax support seems to fit your needs.
In your select2 options object, add an ajax object. Inside this ajax object :
define the regular parameters for an ajax call (url, datatype, delay, etc.)
in the data property, define function that returns the query parameters that should be added to the queryString
in the processResults property, define a function that processes the data returned by the ajax call and returns an object containing a results array (just like the data object you're already building).
Then, you can reuse your templating function.
Here's a working snippet with a random API. Please note the query's term doesn't impact the returned data.
$(document).ready(function () {
$(".products-select2").select2({
width: '100%',
closeOnSelect: false,
placeholder: '',
minimumInputLength: 3,
ajax: {
url: "https://jsonplaceholder.typicode.com/users",
dataType: 'json',
delay: 250,
data: function (query) {
// add any default query here
return query;
},
processResults: function (data) {
// Tranforms the top-level key of the response object from 'items' to 'results'
var results = [];
data.forEach(e => {
results.push({ id: e.id, text: e.name });
});
return {
results: results
};
},
},
templateResult: formatResult
});
function formatResult(d) {
if(d.loading) {
return d.text;
}
// Creating an option of each id and text
$d = $('<option/>').attr({ 'value': d.value }).text(d.text);
return $d;
}
});
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js">
</script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.full.js"></script>
</head>
<body>
<select name="filtre_products[]" class="form-control products-select2" multiple>
</select>
</body>
</html>

For your ajax success call, do this or similar. i think you don't require such big code. below code snippet is from my working script.
success: function (data) {
var dbSelect = $('#ddlItems'); // id for Dropdown list
dbSelect.empty();
result = JSON.parse(data);
// Parse result object and create your array collection in ajax_r object
for (var i = 0; i < ajax_r.length; i++) {
dbSelect.append($('<option/>', {
value: ajax_r.item[i].Value,
text: ajax_r.item[i].Text
}));
}
}

Related

How to property update bootstrap autocomplete source after Ajax call

I am currently implementing the autocomplete bootstrap control from here. I only want to populate the source when characters are more than 2. I'm wondering how do I populate my type ahead source after a successful ajax call.
https://github.com/bassjobsen/Bootstrap-3-Typeahead.
var $input = $(".typeahead");
$input.keyup(function () {
var count = $input[0].value.length;
if (count >= 3) {
$.ajax({
type: "GET",
url: '/Home/GetProducts',
data: {
characters: $input[0].value
},
success: function (response) {
$input.typeahead({
source: response,
autoSelect: true
});
}
});
}
});
When I put a breakpoint at response, this is the result
So my ajax query works, but the type ahead doesn't populate with the results and aren't searchable.

Change dropdown menu items format using results from API - Semantic UI

Currently setting up a dropdown which gathers results from an API. I have set it up as follows:
$("#my-dropdown").dropdown({
minCharacters: 2,
apiSettings: {
cache: false,
url: getCorrectUrl(),
method: 'POST',
onResponse: function(users) {
var response = {
success: true,
results: []
};
$.each(users, function(index, item) {
response.results.push({
name: item.name,
value: item.id
});
});
return response;
}
}
});
And it is returning the correct data, just not in the form that I want. I would like to format the menu items how I want.
Specifically, what I'm currently getting is:
...but what I want is:
I have seen the answer to this question, which uses the onShow function to change the items into a custom form, but is manual manipulation of the DOM the only way to do it? Or is there a built in method to specify custom format menu items for use in a API-powered dropdown menu?
I have done this before, it involves defining a custom type of a template for generating the HTML for the results from the response.
I would go to dropdown.js in your Semantic/components directory and find:
$.fn.dropdown.settings.templates = { //line 3715 in version 2.2
you will find some predefined templates there for how the JSON is used to generate the results.
I didn't edit the code there, instead I copied the usual results template (templates.dropdown), tweaked the copied contained js to fit my results and created my own function from it in my own js file:
function addDropdownTemplate(name){
$.fn.dropdown.settings.templates[name] = function (response) {//use response
//use the edited version of the default template here
}
}
When you call the above function, you will add your own template for converting the response to the HTML results, to use it just specify the type of template you will use in the api settings:
apiSettings: {
//your other settings as in the question above
type: 'imageResult' //imageResult is an example, you can call it whatever
//you like as long as it's the same as what you passed
//to your function as the name parameter
}
I am looking at my code and I didn't even attach an onResponse event in the apiSettings, wasn't necessary.
Having the same problem, I came accross that post and tried to apply the best answer solution, but failed to make it work.
However, it led me to discover another way to achieve what you want to do, using the "onSuccess" callback under "apiSettings":
$('.player-dropdown.remote').dropdown({
on: 'click',
direction: 'downward',
allowAdditions: false,
allowReselection: true,
fireOnInit: false,
apiSettings: {
url: 'search?q={query}',
onSuccess: function(response) {
var html = '' ;
$('.player-member-menu').empty();
$.each(response.results, function(index, item) {
html += '<span class="select-player nowrap item " data-value="' + item.value + '">'
+ '<small class="description right-floated">' + item.description + '</small>'
+ '<span class="text">' + item.name + '</span>'
+ '</span>';
});
$(this).find('.player-member-menu').html(html) ;
},
},
minCharacters : 3,
searchDelay: 500,
duration: 500,
saveRemoteData: false,
filterRemoteData: false,
showOnFocus: true,
fullTextSearch: true,
});
In my example, the results array is formatted as asked in the docs, excepted that each item has 3 parameters instead of 2: name, value and description.

Adding an item to a dropdownlist which is in another partial view without refreshing the view

I am new to asp.net mvc and I am facing this issue with dropdownlist now.
Sorry if I am asking a stupid question.
I have a main View AbcView which is bound to a Controller AbcController which passes an AbcModel to the view.
I have 2 partial views inside this AbcView which are loaded on button clicks.
Inside the second partial view, I have this code :
#Html.DropDownListFor(model => Model.TrajectoryName, new SelectList(#Model.Trajectories, "Value", "Text"),
new { #class = "dropdown-leftandright", id = drpTrajectory" })
Inside the first partial view, I have some data which is being added to database on some button click like this :
function deleteAction(trajID) {
$.ajax({
type: "POST",
url: "/AbcView/DeleteAction",
data: JSON.stringify({ deleteTraj: trajID }),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
success: function (data) {
// I want to update the drpTrajectory dropdownlist here
},
error: function (e) {
return "error";
}
});
}
My issue is I want to access the drpTrajectory in second partial view inside this function. I want to add some item to this particular drop down list.
I tried to access the dropdownlist by using $('#drpTrajectory') and tried to add an item. But it is failing.
I tried to add data like this
$('#drpTrajectory ').add(val(data.x).text(data.y));
data will be a member from a IEnumerable<SomeClass> dataList and SomeClass contains id and name which could be the value and text respectively.
I am already updating the model data during the button click ie #Model.Trajectories is getting updated.
So please help me to add an item to this dropdownlist which is in second partial view from my first partial view without refreshing the entire view.
Any idea?
Assuming your method is returning a collection of objects, then to create and append an option to a <select> you need
var select = $('#drpTrajectory') // cache it
$.ajax({
type: "POST",
url: '#Url.Action("DeleteAction", "AbcView")',
data: { deleteTraj: trajID },
dataType: "json",
success: function (data) {
select.empty() // if you need to remove the existing options
$.each(data, function (index, item) {
// Create an option element
var option = $('<option></option>').val(item.id).text(item.name);
// append it to the select element
select.append(option);
})
},
....
});
Side notes
Always use #Url.Action() to ensure that your url's are correctly
generated
There is no need to stringify() the data and then add the
contentType` option
Your controller method should be returning a collection of anonymous
objects containing just the 2 properties you need (there is no point
sending back extra data that's not use)
var data = dataList.Select(x => new { id = x.id, name = x.name });
return Json(data)
Your use of new SelectList(#Model.Trajectories, "Value", "Text")
suggests that the property Trajectories is already
IEnumerable<SelectListItem>. If that is the case, there is no
point creating an identical SelectList from the original one, so
just use
#Html.DropDownListFor(model => Model.TrajectoryName, Model.Trajectories, new { #class = "dropdown-leftandright", id = drpTrajectory" })
The DropDownListFor() method is already creating
id="TrajectoryName" so there is no real need to overwrite it by
using new { id = drpTrajectory" }
Here is your solution:
success: function (data) {
// I want to update the drpTrajectory dropdownlist here
$.each(data, function (i, item) {
$('#drpTrajectory').append($('<option>', {
value: item.id,
text : item.name
}));
});
}

Passing data from Javascript MVC controller

I'm really new to jQuery and Charts. This is my script, it works fine. It gives me the id of the checkboxes selected by the user. I have a Chart action in my controller which also works fine, but it creates a chart using all my values. I want it to create a chart based on the selected values that are in my script. I don't know how to pass the selected values to my controller.
var checkboxes = $("input[type='checkbox']");
$(function ()
{
function getValueUsingClass() {
/* declare an checkbox array */
var chkArray = [];
/* look for all checkboes that have a class 'chk' attached to it and check if it was checked */
$(".chk:checked").each(function () {
chkArray.push($(this).val());
});
/* we join the array separated by the comma */
var selected = chkArray.join(",") + ",";
/* check if there is selected checkboxes, by default the length is 1 as it contains one single comma */
if (selected.length > 1)
{
alert("You have selected " + selected);
}
else
{
alert("Please check at least one of the checkbox");
}
}
$("#Charter").click(function () {
getValueUsingClass();
});
});
Return the data you want in your js function after populating the variable using return selected; then send it back by posting a form or using ajax.
Bind your data to an element on your View page, for example:
<input name="foo" id="yourId" value="bar" />
then modify it's value:
$('#foo').val(getValueUsingClass());
and pass the model back by posting your form to your controller.
If you wish to send data to your controller async then you can look into Ajax.
You can use ajax to call your controller method within getValueUsingClass().
It would probably look something like this:
$.ajax({
url: "/YourControllerName/Chart",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { arr: chkArray },
success: function () {
// do things upon success
},
error: function () {
alert("Error!");
}
});
That is, providing your Controller action has a parameter named arr, because json maps chkArray to it once it is passed to the Controller.

How to create a dynamic drop down list in html from values in database?

How can I create a dynamic drop down list for my html page but use values from a database to populate the available drop down items in one box based on the value of another? It is identical to something where you select state from one drop down and in dropdown 2 there are the cities, you select city and you can select the zip codes from another.I have been searching on the net but I can not find anything that demonstrates using a database. Does anyone have some examples they can post? I am learning using the code below, I can add from a text box but nothing when pulling from a database? Does javascript actually have to make the connection and if so how do you protect the credentials to the dB?
function addCombo() {
var textb = document.getElementById("txtCombo");
var combo = document.getElementById("combo");
var option = document.createElement("option");
option.text = textb.value;
option.value = textb.value;
try {
combo.add(option, null); //Standard
}catch(error) {
combo.add(option); // IE only
}
textb.value = "";
}
For AJAX, check this example. The are 2 dropdowns.
Services
Doctors
So when you choose a service, then you can get the doctors. When you choose a doctor it redirects you to a URL. Hope it helps!
HTML
Click to select a service
Service 1
Service 2
Service 3
<select id="doctors">
</select>
JS
// The data that the service should return
// JSFiddle will echo it back for us on that URL
var doctors = {
success: true,
doctors: [
{
id: 71,
name: "George"
},
{
id: 72,
name: "James"
}
]
}
// This is what your JSON from PHP should look like
var jsonDoctors = JSON.stringify(doctors);
console.log(jsonDoctors);
// Bind change function to the select
jQuery(document).ready(function() {
jQuery("#services").change(onServiceChange);
});
function onServiceChange()
{
var serviceId = jQuery(this).val();
$.ajax({
url: '/echo/json/',
type: 'post',
data: {
serviceId: serviceId,
json: jsonDoctors // jsFiddle echos this back to us
},
success: onServicesRecieveSuccess,
error: onServicesRecieveError
});
}
function onServicesRecieveSuccess(data)
{
// Target select that we add the states to
var jTargetSelect = jQuery("#doctors");
// Clear old states
jTargetSelect.children().remove();
// Add new states
jQuery(data.doctors).each(function(){
jTargetSelect.append('<option value="'+this.id+'">'+this.name+'</option>');
});
}
function onServicesRecieveError(data)
{
alert("Could not get services. Please try again.");
}

Categories

Resources