Liferay Alloy UI - Clearing cache of dependent AutoCompleteList - javascript

I need to have two dependent AutoCompleteList in my Liferay portlet page. When I select some value from first AutoCompleteList then based on it's selected value I need to change the second AutoCompleteList source data. Based on information available, I have done coding and it is working fine except one issue.
When I select item in first AutoCompleteList then second AutoCompleteList gets populated with certain values based on my first list's selected item. Then if I change my selection again in first list, second AutoCompleteList gets updated with new possible values. But it appends the new possible values in the existing list or can say keep caching of data from both cases. But I need to show only possible values in list based on current selection of first list. For example, for selected value 1 in first list, if initially it was showing [A, B] in second list, after changing selection in first list from 1 to 2, it is showing [[A,B]+[C,D]].
Below here is part of that code. I tried setting "enableCache: 'false' " in second AutoComepleteList but not working.
<aui:script>
AUI().use('autocomplete-list','aui-base','aui-io-request','autocomplete-filters','autocomplete-highlighters',
function (A)
{
A.io.request('<%=getUrl %>',{
dataType: 'json',
method: 'GET',
on: {
success: function() {
new A.AutoCompleteList(
{
allowBrowserAutocomplete: 'false',
activateFirstItem: 'true',
inputNode: '#<portlet:namespace />name',
resultTextLocator: 'name',
render: 'true',
resultHighlighter: 'phraseMatch',
resultFilters:['phraseMatch'],
source:this.get('responseData'),
on: {
select: function(event) {
var result = event.result.raw;
A.one('#<portlet:namespace/>pk').val(result.id)
}
},
})
}}
});
});
</aui:script>
<aui:input id="pk" name="pk" label="Primary Id"
onChange='<%= renderResponse.getNamespace() + "fetchDisplayValues();"%
/>
Liferay.provide(
window,
'<portlet:namespace />fetchDisplayValues',
function() {
var A = AUI();
var pk = A.one("#<portlet:namespace/>pk");
var id = pk.get("value");
var url = '<%=getValues %>';
url = url+"&<portlet:namespace/>id="+id;
var datasource = new A.io.request(url,{
dataType: 'json',
method: 'GET',
on: {
success: function(){
var data = this.get('responseData');
new A.AutoCompleteList(
{
allowBrowserAutocomplete: 'false',
enableCache: 'false',
activateFirstItem: 'true',
inputNode: '#<portlet:namespace />displayName',
resultTextLocator: 'name',
render: 'true',
resultHighlighter: 'phraseMatch',
resultFilters:['phraseMatch'],
source:this.get('responseData'),
on: {
select: function(event) {
var result = event.result.raw;
A.one('#<portlet:namespace/>displayId').val(result.id);
}
},
})
}
}
});
})
</aui:script>
Please help me to resolve this issue. Thanks in advance.

Related

How can ajax based Select2 pre-population be formatted?

We've found several examples of pre-populating selected option for Select2, however none of them we could find deal with formatted list and selection options. We have a JS fiddle at https://jsfiddle.net/gpsx62de/26/ that illustrates the issue. In that fiddle, you can type and L or whatever into the select search and the data is returned, the list is formatted, and if you select something, the selection is formatted.
However if you click the button in that JS Fiddle which is intended to simulate pre-population per https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2 the data is returned (you can uncomment the console.log to see it), but the formatted selection shows undefined for the intended values. Does anyone know of a way to get the formatted values for pre-populated data to display correctly?
// Set up the Select2 control
$('#mySelect2').select2({
ajax: {
url: '/api/students'
}
});
// Fetch the preselected item, and add to the control
var studentSelect = $('#mySelect2');
$.ajax({
type: 'GET',
url: '/api/students/s/' + studentId
}).then(function (data) {
// create the option and append to Select2
var option = new Option(data.full_name, data.id, true, true); //**** DOES IT MATTER WHAT IS PASSED HERE BECAUSE WE ARE NOT DISPLAY THE OPTION TEXT?? ***
studentSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
studentSelect.trigger({
type: 'select2:select',
params: {
data: data //**** THIS DOES NOT SEEM TO SUPPORT FORMATTED SELECTIONS, SO HOW CAN THIS BE DONE? ***
}
});
});
The problem is in format_selection function. The format of the object it receives depends on how it was created. When you use new Option(text, value) it receives only the properties of this Option object, not your original object containing all user info.
A workaround is to check of either possible values in the fuction:
function format_selection(obj) {
let name = obj.name || obj.element.text;
let email = obj.email || obj.element.email;
return $(`<div><b>${name}</b></div><div>(${email})</div>`);
}
For this to work you should append the de property on you Option object:
var option = new Option(data.name, data.id, true, true);
option.email = data.email;
$('#sel').append(option).trigger('change');
The problem, in https://jsfiddle.net/gpsx62de/26/ is with the
function format_selection(obj) {
// Just add this to see the obj
console.log(obj);
return $(`<div><b>${obj.text}</b></div><div>(${obj.id})</div>`);
}
The obj object just contains the Option class data, so:
id: "1",
selected: true,
text: "Leanne Graham",
title: ""
So you have to find a way to pass "data.email" to the "format_selection" method
EDIT
This could be a solution
$('#btn').on('click', function() {
$.ajax({
type: 'GET',
url: 'https://jsonplaceholder.typicode.com/users/1'
})
.then(function(data) {
console.log(data)
// create the option and append to Select2
$('#sel').append($('<option />') // Create new <option> element
.val(data.id) // Set value
.text(data.name) // Set textContent
.prop('selected', true)
.attr('data-name', data.name) // Don't know why the .data(key, value) isn't working...
.attr('data-email', data.email))
.trigger('change');
}); //then
}); //click
And
function format_selection(obj) {
return $(`<div><b>${obj.element.dataset.name}</b></div><div>(${obj.element.dataset.email})</div>`);
}
This is the fiddle https://jsfiddle.net/947jngtu/

Use multiselect with dynamically generated select

I am trying to use the multiselect plugin I found on here:
How to use Checkbox inside Select Option
The question above is for a <select> with hard coded <options>.
The <select> I am using generates <options> using jQuery and PHP with this function:
function initializeSelect($select, uri, adapt){
$.getJSON( uri, function( data ) {
$select.empty().append($('<option>'));
$.each(data, function(index, item) {
var model = adapt(item);
var $option = $('<option>');
$option.get(0).selected = model.selected;
$option.attr('value', model.value)
.text(model.text)
.appendTo($select);
});
});
};
initializeSelect($('#salesrep'), 'process/getSalesReps.php', function (item) {
return {
value: item.final_sales_rep,
text: item.final_sales_rep
}
});
I have used the above function several times in different projects, as it successfully creates all of the options brought in by the PHP process. Unless requested, I will not show the code for the process. Just know I am indeed retrieving a group of names and displaying them in the dropdown.
Right beneath the function above is where I call the multiselect feature:
$('select[multiple]').multiselect();
$('#salesrep').multiselect({
columns: 1,
placeholder: 'Select Reps'
});
The HTML for the select is as follows:
<select class="form-control" name="salesrep[]" multiple id="salesrep"></select>
Using all of the above, the output looks like this:
Upon inspecting the element, I can see all of the sales reps names. This tells me that the initializeSelect function is working properly.
Therefore I think the issue must have something to do with the multiselect.
Ajax calls are asynchronous. You call multiselect() before the ajax call has had time to complete and therefore the option list is still empty at the point you call the multiselect() function.
Either move the $('#salesrep').multiselect({.. bit to inside the getJSON method or call the multiselect refresh function after the option list has been populated as I am doing here. (Untested.)
function initializeSelect($select, uri, adapt){
$.getJSON( uri, function( data ) {
$select.empty().append($('<option>'));
$.each(data, function(index, item) {
var model = adapt(item);
var $option = $('<option>');
$option.get(0).selected = model.selected;
$option.attr('value', model.value)
.text(model.text)
.appendTo($select);
});
//now that the ajax has completed you can refresh the multiselect:
$select.multiselect('refresh');
});
};
initializeSelect($('#salesrep'), 'process/getSalesReps.php', function (item) {
return {
value: item.final_sales_rep,
text: item.final_sales_rep
}
});
$('select[multiple]').multiselect();
$('#salesrep').multiselect({
columns: 1,
placeholder: 'Select Reps'
});

mdb_autocomplete drop down does not close on click event

In certain cases, usually after values have been cached from an initial search, I cannot get the mdb_autocomplete drop down to close on a single click. I often have to double click on my selection to get it to close. I am dynamically populating the values in the drop down via an Ajax call to a service method via and controller action method that searches the active directory for the first 30 name values. No call back occurs until a user enters at least 3 values into the mdb_autocomplete selection box. The callback and population of the drop down is working very well, but the click event following the selection of a value often will not close the dropdown. Additionally, we are being forced to use mdb boostrap over the normal bootstrap library. I have included the view, service, and typescript code that is being used to generate and populate the drop down.
View:
<div class="form-group">
<label class="font-weight-bold" for="RequestorSearchInput">Requestor</label>
<input type="text" id="RequestorSearchInput" name="RequestorSearchInput" class="form-control mdb-autocomplete" />
<span id="loading_data_icon"></span>
</div>
Service Method:
public List<string> GetRequestor(string aRequestor)
{
IEnumerable<Dictionary<string, string>> requestorNames;
using (ActiveDirectoryService service = new ActiveDirectoryService(<LDAP Domain Name>))
{
string[] propertiesToLoad = new string[] { "displayName" };
//requestorNames = service.SearchByPartialUsername(aRequestor, propertiesToLoad).Take(30).Union(service.SearchBySurname(aRequestor, propertiesToLoad).Take(30));
requestorNames = service.SearchBySurname(aRequestor, propertiesToLoad).Take(30);
}
return requestorNames.SelectMany(x => x.Values).Where(y => y.IndexOf(",", StringComparison.Ordinal) >= 0).Distinct().ToList();
}
TypeScript:
private handleRequestorSearch() {
let options: string[] = new Array();
// #ts-ignore
let searchval = $("#RequestorSearchInput").val().length;
if (searchval >= 3) {
$.ajax({
url: main.getControllerHREF("GetRequestor", "Search"),
method: "POST",
data: {
requestor: $("#RequestorSearchInput").val()
},
async: false,
dataType: "json",
success: function (names) {
$.each(names, function () {
options.push(this);
});
// #ts-ignore
$("#RequestorSearchInput").mdb_autocomplete({
data: options
}).select(function () {
$("#RequestorSearchInput").focus;
});
}
});
}
}

How to pass selected value as extra parameter to ajax call

my coding part
$("#demo-input").tokenInput("data/autosuggest-search-city.php",
{
searchDelay: 2000,
minChars: 3,
tokenLimit: 10
});
I want to send the selected values as extra parameter to "data/autosuggest-search-city.php".
For example,
Initially I search and select one value from list
then again searching, this time I want to send the 1st selected value to server.
How to do this?
TokenInput plugin doesn't support that natively.
You can however make a simple workaround to update "AJAX url" whenever a token is added or removed from selection.
Use onAdd and onDelete callbacks to trigger "AJAX url" changes;
Get selected tokens using selector.tokenInput("get") method;
Set the new "AJAX url" by updating .data("settings").url of the element;
// cache the original url:
var token_url = "data/autosuggest-search-city.php";
$("#demo-input").tokenInput(token_url, {
searchDelay : 2000,
minChars : 3,
tokenLimit : 10,
onAdd : function(){
urlChange.call(this);
},
onDelete : function(){
urlChange.call(this);
}
});
function urlChange(){
var tokens = '', token_list = $(this).tokenInput("get");
// proceed if any token/s are selected:
if(token_list.length){
// loop through the selected tokens (if more than one is selected)
$.each(token_list, function(i, token){
// use token "id" (or "name" if you wish) and separate them with comma:
tokens += token.id + ',';
});
// update url:
$(this).data("settings").url = token_url + '?selected_tokens='+tokens.replace(/,+$/,'');
}else{
// leave original url if no tokens are selected:
$(this).data("settings").url = token_url;
}
};

changing the values of countries with flag in select box1 by onchange with ajax

i am stuck at one point where i need to populate the country after the ajax resp but it is not showing selected here is the image
if i am selecting other than african countries i should get all the countries in drop down which i am getting as you can see in the pic but the first one is not selected as you can see in the pic
here is my code in jquery
var country_data=countries;
$.ajax({
type: "POST",
url: "ukcountry_ajax.php",
datatype:"json",
data:{ country:country_data}
}).done(function( data )
{
var final_country=JSON.parse(data);
var $select=$('#tocurrency');
$select.find('option').remove();
$("#tocurrency").select2('data', {id: '', text: ''});
$.each(final_country,function(index)
{
var image=final_country[index].final_image;
var name=final_country[index].countryname;
$('#tocurrency').append("<option value="+image+">"+name+"</option>");
});
});
can any body suggest where i am wrong code is wrkng fine in ie,chrome and FF but not getting selected the first country in the select box as it is showing empty
TIA
You can do it like this by first child element as a selected value.
Remove this line
$("#tocurrency").select2('data', {id: '', text: ''});
and update your each loop like this
$.each(final_country,function(index)
{
var image=final_country[index].final_image;
var name=final_country[index].countryname;
if(index==0)
{
$('#tocurrency').append("<option selected value="+image+">"+name+"</option>");
}
else{
$('#tocurrency').append("<option value="+image+">"+name+"</option>");
}
});
$("#tocurrency").select2('data', {id: $('#tocurrency option:first-child').val(), text:$('#tocurrency option:first-child').text() });
I hope it will help. Thanks

Categories