Angular-UI Select2 directive Search functionality not working - javascript

I'm using the angular-ui select2 directive. I know it's now deprecated but my application is using this directive throughout and there is an improvement I want to make.Soon, we will migrate to the new ui=select alternative.
I'm loading the json data via an ajax call as per the example here http://select2.github.io/select2/. The data is loading correctly and can be selected, however I cannot search and narrow down/filter the results. From what i understand this is supported in the directive. when i type something, the data refreshes but doesn't filter according to the search terms. below is my code
<input type="text" id="users" ui-select2="filters.select2Test" ng-model="filters.model.users"
data-placeholder="Pick a user" ng-required="true" style="width: 300px" />
$scope.filters = {
select2Test: {
id: function(user) {
return user.code;
},
minimumInputLength: 3,
multiple: true,
ajax: {
url: 'api/employee', //This URL points to an internal location and wouldn't work
dataType: 'json',
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
results: function(data, page) {
return { results: data };
}
},
formatResult: function(data) {
return "<div class='select2-user-result'>" + data.name + "</div>";
},
formatSelection: function(data) {
return data.name;
},
initSelection: function(element, callback) {
var data = [];
$(element.val().split(",")).each(function(i) {
var item = this.split(':');
data.push({
id: item[0],
title: item[1]
});
});
callback(data);
}
}
}

A matcher needs to be added in your select2 options:
select2Test: {
...
matcher: function(term, text, option) {
return option.name.includes(term);
},
...
}

Related

Select2, Symfony: Autocomplete with remote data not working

I'm trying to implement an autocomplete search when searching for a city on my website (carpooling).
I made a controller searchCity which return a json with the cities:
/**
* #Route ("/city/{term}")
*/
public function searchCity($term)
{
$query = $this->getDoctrine()->getRepository('App:Ville')
->createQueryBuilder('v')
->select('v.id, v.nomReel AS text')
->where('v.nomSimple LIKE :term')
->setParameter('term', $term.'%')
->getQuery()
->getResult();
$query = array('results' => $query);
return new JsonResponse($query);
}
For exemple if I go to /city/Paris I'll get :
{"results":[
{"id":30438,"text":"Paris"},
{"id":29427,"text":"Paris-l\u0027H\u00f4pital"}, //I know single quotes
{"id":33294,"text":"Parisot"}, //don't work
{"id":33531,"text":"Parisot"}]}
select :
<div class="container">
<select id="citySelect" class="select2 select2-dropdown select2-search" name="term">
</select>
</div>
javascript :
$(document).ready(function(){
$("#citySelect").select2({
placeholder: "Select city",
ajax: {
dataType: "json",
url: function (params) {
return '/city/' + params.term;
},
processResults: function (data) {
return {
results: $.map(data, function(obj) {
return { id: obj.ime, text: obj.ime };
})
};
}
}
});
});
When I search a city nothing shows up (searching ... and nothing)
with the console log I can see that data is there and well formated but the cities are not showing on the dropdown menu.
I think that my problem is with my javascript code and my comprehension of select2.
Regards
UPDATE :
js :
$(document).ready(function(){
$(".select2").select2({
placeholder: "Select city",
ajax: {
dataType: "json",
url: function (params) {
return '/city/' + params.term;
},
processResults: function (data) {
return {
results: data.results //return data directly
};
}
}
});
});
I guess when transforming data you wanted
return { id: obj.id, text: obj.text };
instead of
return { id: obj.ime, text: obj.ime };
Also looking at the json you posted you could probably (not tested) just do
processResults: function (data) {
return {
results: data.results;
};
}

Set data of a Multiple Select2 element through javascript

I'm loading multiple values into a Select2 element through Javascript, ajax and jquery. While the data is loading properly and can be accessed once loaded, I'm unable to set stored data in the Select2 element.
Edit: I'm using Select2 v3.5.
My code:
HTML:
<input class="jsData" style="width: 100%" id="select2Data"></input>
Javascript:
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
contentType: 'application/json',
url: '<%=Url.Action("GetData","Controller")%>',
type: 'POST',
dataType: 'json',
data: function (term) {
return {
sSearchTerm: term
};
},
results: function (data) {
return {
results: $.map(JSON.parse(data), function (item) {
return {
text: item.term,
slug: item.slug,
id: item.Id
}
})
};
}
},
multiple: true
});
So, this creates a Select2 element where I can traverse to and from a database and load data depending on what I've typed. I can also access the data (entered by the user) using the following line:
$('.jsData').select2('val')
The above line returns an array, which I can store in the database. My current objective is to set the stored data back into the Select2 element. Any help in this matter would be most welcome.
Update: A relevant link for what I want to accomplish:
https://select2.github.io/examples.html#programmatic
I want the example of setting multiple elements in Select2. However, the difference would be in the fact that the example in the Select2 documentation brings data at the time of loading the page, while I will be making trips to fetch the data.
The Select2 v3.5.4 docs are a bit confusing around this. I think there's a typo in the docs that's misleading.
First, notice that when I retrieve the data from the remote source I'm returning it as an object in the format of {id: ##, name: NAME}.
The first step is to add the initSelection parameter and pass the function to retrieve the previously selected items.
The next step, where I believe there's a typo, is to define the formatSelection parameter (not the formatResult it states in the docs). This function defines how the previously selected result is displayed. In this case I'm merely showing the name property of the result.
The formatResult parameter defines how newly selected options are displayed. You'll notice formatResult and formatSelection are the same below. I could have reused a single function but felt this was better for demonstration.
$(document).ready(function() {
function formatResult(data) {
return data.name;
};
function formatSelection(data) {
return data.name;
}
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
url: "https://jsonplaceholder.typicode.com/users",
type: "GET",
dataType: "json",
results: function(data) {
return {
results: $.map(data, function(user) {
return {
name: user.name,
id: user.id
};
})
};
}
},
initSelection: function(element, callback) {
var id = $(element).val();
if (id !== "") {
$.ajax("https://jsonplaceholder.typicode.com/users/" + id, {
dataType: "json"
}).done(function(data) {
callback(data);
});
}
},
formatResult: formatResult,
formatSelection: formatSelection,
multiple: true
});
});
Here's the full working example:
$(document).ready(function() {
function formatResult(data) {
return data.name;
};
function formatSelection(data) {
return data.name;
}
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
url: "https://jsonplaceholder.typicode.com/users",
type: "GET",
dataType: "json",
results: function(data) {
return {
results: $.map(data, function(user) {
return {
name: user.name,
id: user.id
};
})
};
}
},
initSelection: function(element, callback) {
var id = $(element).val();
if (id !== "") {
$.ajax("https://jsonplaceholder.typicode.com/users/" + id, {
dataType: "json"
}).done(function(data) {
callback(data);
});
}
},
formatResult: formatResult,
formatSelection: formatSelection,
multiple: true
});
});
.jsData {
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.css" rel="stylesheet"/>
<input class="jsData" style="width: 100%" id="select2Data" value="10"></input>

set data attributes with ajax and select2

I'm trying setup data attributes into select2 options but without success, at this moment i have the following JS code
_properties.$localElement.select2({
ajax: {
url: "url",
type: "POST",
dataType: 'json',
delay: 250,
data: function (params) {
return {
name: params.term, // search term
type: 1
};
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
source: item.source,
id: item.id
}
})
};
},
cache: true
},
//define min input length
minimumInputLength: 3,
});
And i want setup a data-source for the selected option value.
I find the solution, looks that resultTemplate dont format the "visual" selected option , need to use templateSelection option:
templateSelection: function(container) {
$(container.element).attr("data-source", container.source);
return container.text;
}
I solved this problem.
$('select').on('select2:select', function (e) {
var data = e.params.data;
$("select option[value=" + data.id + "]").data('source', data.source);
$("select").trigger('change');
});
You can actually use the exact syntax, that you already used. The "source-attribute" just needs to be accessed via data().data.source of the specific select2-option.
So keep your processResults function like you did:
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
source: item.source,
id: item.id
}
})
};
},
and if you want to retrieve the source of the selected option, you can do it like this:
var selectedSelect2OptionSource = $("#idOfTheSelect2 :selected").data().data.source;
In fact you can set any variable you want in your processResults function and then select it via data().data.variableName!

Select2 preloaded tags in Select2 input box

I have a Select2 input that is working great. The user can start typing and select an option from the dropdown menu and it adds a tag into the input field, they can also create their own tags thanks to the createSearchChoice function.
My scenario is when a user types in a customer's name who already exists, it locks on, and I want it to populate the field with tags (usual suppliers). The user can then delete or add more tags if they want.
My code is:
$('#usualSuppliers').select2({
containerCssClass: 'supplierTags',
placeholder: "Usual suppliers...",
minimumInputLength: 2,
multiple: true,
placeholder: 'Usual suppliers...',
createSearchChoice: function(term, data) {
if ($(data).filter(function() {
return this.name.localeCompare(term) === 0;
}).length === 0) {
return {id: 0, name: term};
}
},
id: function(e) {
return e.id + ":" + e.name;
},
ajax: {
url: ROOT + 'Ajax',
dataType: 'json',
type: 'POST',
data: function(term, page) {
return {
call: 'Record->supplierHelper',
q: term
};
},
results: function(data, page) {
return {
results: data.suppliers
};
}
},
formatResult: formatResult,
formatSelection: formatSelection,
initSelection: function(element, callback) {
var data = [];
$(element.val().split(",")).each(function(i) {
var item = this.split(':');
data.push({
id: item[0],
title: item[1]
});
});
//$(element).val('');
callback(data);
}
});
How can I make it pre-populate the input with tags that come in from an Ajax request?
I managed to solve the issue thanks to this post:
Load values in select2 multiselect
By using trigger.

X-editable with select2 and Ember.js

I'm trying to use x-editable with select2 in an Ember.js application.
I created the following editable element:
Test parent
And used this JavaScript:
$(function() {
$.fn.editable.defaults.mode = 'inline';
$('.editable').editable({
type: 'select2',
select2: {
placeholder: "Search for a parent...",
minimumInputLength: 3,
multiple: true,
ajax: {
url: 'http://localhost:8001/api/parents',
dataType: 'json',
data: function (term, page) {
return { q: term }; // search term
},
results: function (data, page) {
return {results: data};
}
},
formatResult: function(result) {
return result.first_name + ' ' + result.last_name;
},
formatSelection: function(selection) {
return selection.first_name + ' ' + selection.last_name;
}
},
// Used for sending JSON instead of form data
params: function(params) {
return JSON.stringify(params);
}
});
});
When I click Test child the ajax spinner appears and the following error in console is shown: Uncaught TypeError: Cannot read property 'id' of null
It refers to this:
$.fn.select2.defaults = {
...
id: function (e) { return e.id; },
...
}
What could I be doing wrong here? Thanks!
Are you tapping into the X-Editable’s success method?
Here's an interesting article on how a company implemented X-Editable into an Ember app: http://blogs.visoftinc.com/2014/11/12/using-xeditable-with-ember/

Categories