Unable to recreate multiselect with updated params, destroy does not allow recreate - javascript

I am using the bootstrap multiselect from https://github.com/davidstutz/bootstrap-multiselect.
Problem Scenario: Based on the users input, I am receiving the options to be included through an ajax call.
I want to include the select all and filter only when there are more than 1 option. I am trying to add the select all and filter properties dynamically. But the problem is, the multiselect seems to remember the properties I set in the previous call.
When the page is loaded, the ajax call returns 3 options, the select all and filter are enabled for the multiselect. But when the user changes input, the ajax call now returns only 1 option. I am updating the function params as in (a) and trying to recreate the multiselect as in (b)
(a) function updateParams(options, params){
if (options.length<1 ){
params.includeSelectAllOption = false;
params.enableFiltering = false;
params.enableCaseInsensitiveFiltering = false;
} else {
params.includeSelectAllOption = true;
params.enableFiltering = true;
params.enableCaseInsensitiveFiltering = true;
}
return params;
}
(b) {....
// $(ele).multiselect('destroy');
$(ele).html('');
var params = $.extend(true, {}, paramsGiven);
params = updateParams(options, params);
$(ele).multiselect(params);
$(ele).multiselect("rebuild");
...}
I copied the params so that they donot persist between user inputs. I printed the params and paramsGiven before and after updating and they carry the properties as I expected. The above code does not seem to recreate the multiselect with new params. I also tried destroying and recreating but it just destroys and does not recreate.
Could anyone please help me understand whats going wrong here?

Related

Presetting kendo DataSource PageSize to "All"

Whenever a user changes the pagination on a grid, I save the setting in localStorage and retrieve it to set it back whenever the user navigates again to the page. To retrieve it I am using the pageSize property of the dataSource where I pass an IIF like so:
pageSize: function () {
var pageSize = 10;
if (window.localStorage) {
var userPreferencePageSize = localStorage.getItem("somegridPageSize");
if (userPreferencePageSize === parseInt(userPreferencePageSize)) {
userPreferencePageSize = parseInt(userPreferencePageSize);
}
if (!isNaN(userPreferencePageSize)) {
pageSize = userPreferencePageSize;
}
}
return pageSize;
}()
This worked well but a requirement appeared for the user to be able to set the pageSize to "All". Kendo handles "All" in the Grid so I thought this will let me set the dataSource pageSize to the string "All" (pageSize="All") as well. When I do it however the grid starts displaying NaN of X records and displays an empty grid. So the question is.. how do I preset the pageSize of the dataSource to just "All"?
NOTE: An alternative is to just fetch the grid maximum total count and then replace the number displayed in the dropdown with jquery text("All) but that looks like a hack and it seems to me this should already be inbuilt into the framework but I can't find anything in the doc's.
EDIT: This is getting even funnier. Due to lack of other options I implemented it like in the note and just set the dataSource pageSize directly:
$("#Grid").data("kendoGrid").dataSource.pageSize(pageSize);
But this is causing the filters on grid to malfunction and throw "string is not in correct format" (misleading error) error from the endpoint. After enough research I found out its caused by the DataSourceRequest doing some unidentifiable shuru buru in the background. Since setting the dataSource pageSize causes issues, I tried just setting the dropdown programatically and let kendo trigger the request to update pageSize itself like so:
var selectBox = $(".k-pager-sizes").find("select");
selectBox.val(pageSize);
selectBox.find("option[value='" + pageSize + "']").prop('selected', true);
But the grid doesn't let me do it and keeps reverting any changes I do inside the DOM from javascript.
So the question is, how in earth can you change the pageSize of a server-side kendo grid from javascript (triggering an extra request to endpoint).
To answer the question. This appears to be a bug in Kendo. Setting the pageSize to 0 (shortcut for "all") after the dataSource was already bound will always result in the grid having issues with any custom filters declared inside of a toolbar template.
To be exact, if you have a custom filter defined inside of the toolbar template:
#(Html.Kendo().TextBox().Name("Filter").Deferred())
You wire it up through the dataSource definition on the grid like:
.DataSource(ds =>
ds.Ajax()
.PageSize(defaultPageSize)
.Read(a => a.Action(actionName, controllerName, new
{
param = Model.param
}).Data("getFilterParameters")))
in javaScript fetching the parameters like:
getFilterParameters: function () {
return this.filterParameters;
},
populating them with a method:
filter: function () {
var grid = $("#Grid").data("kendoGrid");
this.filterParameters = {
param: $("#Filter").val()
};
grid.dataSource.page(1);
}
that has a simple event listener wired to it:
$("#Filter").on("keyup", filter);
Then after changing the pageSize programatically to 0/"all" with:
$("#Grid").data("kendoGrid").dataSource.pageSize(0);
The filter will start to always return NaN as the current page / skip of the filter object passed to the server with the query parameters (even though grid will display the numbers correctly). This will cause a "string is not in correct format" exception inside framework code on the endpoint whenever you try using the filter. A solution to the above is to slightly modify the getFilterParameters method:
getFilterParameters: function (e) {
// Workaround for Kendo NaN pager values if pageSize is set to All
if (isNaN(e.page)) e.page = 1;
if (isNaN(e.skip)) e.skip = 0;
//
return this.filterParameters;
}
This will re-initialize the page and skip values before submitting the filter request. These values will anyway be re-populated on the endpoint with the correct values. Wasn't me who noticed it but another developer working on the project, credit goes to her.

How do I get the values I submitted on a form and pass it onto my modal

I have a form in my jsp wherein I enter a value. This is then inserted into a table on my database. However, I would like to ask the user first to confirm his submission. I used this:
function askConfirmation() {
var confirmSubmission = confirm("Do you wish to add this entry?");
if(confirmSubmission) {
return true;
} else {
return false;
}
}
Although this does the task of suspending submission, it's not quite what I had in mind. I tried using a modal but I don't know how to get the values I used from my EL and place it in the modal after the button click. How do I do this?
I am not quite sure how you have your form inputs setup, but you can pass an object representing all your form inputs as an argument into askConfirmation() function and then pass that to confirm(). This will display to the user all the information in the form. Eg.
function askConfirmation(formInput) {
var confirmSubmission = confirm(formInput);
if(confirmSubmission) {
return true;
} else {
return false;
}
}
So in this way, you can access members/fields in the object and format them accordingly. You can also use jquery dialog() function to achieve this if you don't like the lnf of the window. The bottomline is, just pass the object that represents your inputs value into whatever that is used in displaying to the user for further confirmation. Hope this helps!
As Felipe T mentioned your values are already rendered you just need to get them with javascript here's an example using bootstrap modal https://jsfiddle.net/tf021so9/6/
-
However, I prefer using a confirmation dialog plugin in such cases like this one :https://myclabs.github.io/jquery.confirm/
-

Can ajax be used for faceting/sorting?

I created a select from with popularity,high_to_low and low_to_high as options. I want the page to respond to these options dynamically using the ajax code
var http_option = createRequestObject();
function verifyRequest()
{
var option = document.getElementById("option").value;
if ( option )
{
var url = 'respond.pl?option='+option;
http_option.open('get', url );
http_option.onreadystatechange = handleResponse;
http_option.send(null);
}
}
function handleResponse()
{
if(http_option.readyState == 4 && http_option.status == 200)
{
var response = http_option.responseText; // Text returned FROM perl script
if(response) { // UPDATE ajaxTest content
document.getElementById("id_id").innerHTML = response;
}
}
If the value of the option is 1, images are displayed as stored in DB.
If the option is 2, images are to be displayed in descending order and
If the option is 3, images are to be displayed in ascending order
The respond.pl contain appropriate code for this sorting according to options and display images in a specified div tag.
The problem is that the page responds to the options only once and the next time on changing the option, the value of options shows "on" and not the numerals 1,2,3
I need this not only to sort images but also for faceting. If this is not the right option suggest the appropriate methods used for it.
It looks like your server-side program is returning HTML. And I think that's probably a mistake in this situation. I suggest returning JSON instead. Then, you can create an onChange event handler for your selector which simply re-orders the display. There are almost certainly a number of jQuery plugins that do this without you needing to write very much code.

Setting JQueryUI's autocomplete to render items in a custom way the first time only

I'm using JQuery UI's Autocomplete to load a list of users into a custom control and display them in the regular suggestion list. On page load, I'm calling this field's search() method to populate the form with some initial data.
The problem is that the on page load event displays the suggestion list, as well as populating the custom control. How can I disable the suggestion list for the first query only?
I've tried monkey-patching various methods, and they either break or do nothing.
Of course, the alternative is setting a timeout on a function call to close it, but this will create an ugly flicker I'd like to avoid.
In the end, I overwrote Autocomplete's _suggest method like so:
suggest = function(items) {
ul = this.menu.element.empty().zIndex( this.element.zIndex() + 1 );
this._renderMenu(ul, items);
this.menu.deactivate();
this.menu.refresh();
/* these four lines are the difference between regular autocomplete and this autocomplete */
if (!this.first)
ul.show();
else
this.first = false;
this._resizeMenu();
args = {
of: this.element
}
ul.position($.extend(args, this.options.position));
if (this.options.autoFocus)
this.menu.next(new $.Event("mouseover"));
/* initialisation*/
field.autocomplete().data('autocomplete').first = true;
field.autocomplete().data('autocomplete')._renderItem = renderItem;
field.autocomplete().data('autocomplete')._suggest = suggest;
It's not the most elegant solution, but it works.

Ext JS: Proper technique to filter a combobox?

When I filter a combobox by adding a filter to the underlying store, sometimes the filter works (items are removed) and sometimes it has no effect. I have debugged the filterBy function; it is being called and is returning true/false as I wish to filter/show items.
I read on the ExtJS forums that the, "Combobox uses filtering (even with triggerAction:'all'), so your own trigger gets replaced by the one from the combobox." Two filters?
What is the proper technique to remove temporarily items in an Ext JS combobox?
Use lastQuery: '' in the config.
I faced a similar issue where the combo box would show all the items when the trigger is clicked the first time, irrespective of the filter.
To make sure the filter in the store is not cleared the first time the ComboBox trigger is used, configure the combo with lastQuery=''
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.form.field.ComboBox-property-lastQuery
You want to understand how to reproduce the behaviour of triggerAction:'all', so why not diving into the code ?
Here the source code of the Class ComboBox :
http://docs.sencha.com/ext-js/4-0/source/ComboBox.html#Ext-form-field-ComboBox-cfg-triggerAction
If you look at the code, you'll see that:
1) When trigger is clicked, method doQuery is called.
onTriggerClick: function() {
var me = this;
if (!me.readOnly && !me.disabled) {
if (me.isExpanded) {
me.collapse();
} else {
me.onFocus({});
if (me.triggerAction === 'all') {
me.doQuery(me.allQuery, true);
} else {
me.doQuery(me.getRawValue(), false, true);
}
}
me.inputEl.focus();
}
},
2) In method doQuery, the interesting piece of code is:
if (isLocalMode) {
// forceAll means no filtering - show whole dataset.
if (forceAll) {
store.clearFilter();
} else {
// Clear filter, but supress event so that the BoundList is not immediately updated.
store.clearFilter(true);
store.filter(me.displayField, queryString);
}
}
3) We can see that the method filter of the Store is called.
You have your answer, the proper technique to remove temporarily items in an ExtJS combobox (in a store generally), is using the method filter on the store.
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Store-method-filter
Remember, Your best friend is always documentation!
http://docs.sencha.com/ext-js/4-0/#
You'll need to delete the property 'lastQuery' of the Combobox,
everytime you filter the Store. This is where the ComboBox caches
it's Entryset after it build it up the first time.
So doing something like this:
'window combobox[name=countryselection]' : {
'change' : function(view, newValue){
with(Ext.data.StoreManager.lookup('Subcountries')){
var combobox = Ext.getCmp('MainWindow').query('combobox[name=subcountryselection]')[0];
//force the combobox the rebuild its entryset
delete combobox.lastQuery;
clearFilter();
filter('countryId', newValue);
}
}
}
It works great for me :-)
Keep in mind that filtering does not "recreate" the store with the new data, such that if you filtered a combo with the following values for "apple":
orange
banana
apple
And you clicked on the trigger, "apple" would be shown. However, if you started typing (and have typeAhead: true active, the filtering based on your input will default back to the orange/banana/apple Store.

Categories