I have 10 to 12 select2 dropdowns in complex control, they need to be initialized as select2 dropdown.
On dropdown-open, I make ajax call to load data. The problem comes here, if there are specific data loaded from the server. the drop-down should became multiple select2.
Here is a part of the code:
$selectDropDown.select2({
ajax: {
url: '/GetValues',
dataType: 'json',
data: function (params) {
var query = {
title: name,
}
return query;
},
processResults: function (data) {
if (data.type === '10') {
// I need to make it multiple select here
return {results: data.results};
} else {
var values = getDefaultDataItems();
return {results: values };
}
}
},
allowClear: true,
placeholder: 'Select values'
width: '100%',
});
The data cannot be loaded before initialization of select2, because of optimization reasons.
Currently it works like:
processResults: function (data) {
if (data.type === '10') {
// The hacking way
$selectDropDown.select2({
multiple: 'multiple',
data: data.results
}).select2('open');
} else {
var values = getDefaultDataItems();
return {results: values };
}
}
I want to ask it it he best way to do it?
Is there a build-in functionality?
For me, the best way to do that is add attribute multiple to my select. And change attribute name become array. After that, call .select2(); on my select.
For example, I have select with sub-type class.
$('.sub-type').prop('multiple', true).attr('name', 'sub_type[]').select2();
If you want back to single select again, just write this:
$('.sub-type').prop('multiple', false).attr('name', 'sub_type').select2();
Sorry for the late reply, I just found your question today. I hope my answer can help others.
Related
The example I would like to replicate is this: https://jsfiddle.net/bindrid/hpkqxto6/ . I need to load data from the server, form a grouping of them and when selecting one item from one group all other items inside this particular group would become disabled. The difference is that I must load data from the server using an ajax call inside select2, instead of listing the < option > elements inside the select element and form a grouping this way. I have trouble selecting all available items in the dropdown list during the javascript manipulation in order to disable items from the same group (line 29 in the above example fails due to there being no < option > elements in html, instead I think they are loaded later and javascript is not able to find them).
The html part looks as follows:
<select class="form-control attributoSelect2" name="attributiSelezionati" id="attributoSelect2" value="#Model.AttributiSelezionati"></select>
There are no < option > items inside < select > because the ajax call takes care of populating the list, like this:
$('.attributoSelect2').select2({
placeholder: "Cerca Attributo",
multiple: true,
allowClear: true,
minimumInputLength: 0,
ajax: {
dataType: 'json',
delay: 150,
url: "#Url.Action(MVC.Configurazione.Attributi.CercaAttributi())",
data: function (params) {
return {
search: params.term
};
},
processResults: function (data) {
return {
results: data.map(function (item) {
return {
id: item.Id,
text: item.Descrizione,
children: item.Children.map(function (itemC) {
return {
id: itemC.Id,
groupid: itemC.GroupId,
text: itemC.Descrizione,
};
})
};
})
};
}
}
});
Finally my javascript looks as follows:
$('.attributoSelect2').on("select2:selecting", function (evt, f, g) {
disableSel2Group(evt, this, true);
});
$('.attributoSelect2').on("select2:unselecting", function (evt) {
disableSel2Group(evt, this, false);
});
function disableSel2Group(evt, target, disabled) {
var selId = evt.params.args.data.id;
var group = evt.params.args.data.groupid;
var aaList = $(".attributoSelect2 option");
$.each(aaList, function (idx, item) {
var data = $(item).data("data");
var itemGroupId = data.groupid;
if (itemGroupId == group && data.id != selId) {
data.disabled = disabled;
}
})
}
The problem is that this line:
var aaList = $(".attributoSelect2 option");
does not load all the option elements because they are not loaded yet. They would be loaded later on using the ajax call. Does anyone have an idea of how to resolve this problem?
This question has been as a lot so please forgive me asking again.
I have a grid loaded from a url.
I use loadonce: true
I use filtertoolbar:
$("#status").jqGrid('filterToolbar', { stringResult:true, searchOnEnter:false, autosearch: true, defaultSearch: "cn" });
I have a dropdown search list from which I can select what I'm looking for. Works great.
I have a navbutton I click to initiate a reload every 30 seconds. Works great.
$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-play', onClickButton: function ()
{
stint = setInterval (function() {
postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;
$("#status").jqGrid('setGridParam',{
url: './ar_status.cgi?systemtype=' + systype,
datatype: "json",
postData: postfilt,
search: true,
loadtext: "Refreshing grid...",
loadonce: true,
loadui: "block"
});
$("#status").jqGrid().trigger("reloadGrid");
}, 30000);
},
title: 'Start Auto Refresh (every 30 sec.)'
});
Using google chrome I can see the filters that were specified being posted to the server:
systemtype:production
_search:true
nd:1358887757603
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"}]}
I can change the filter between reloads and see the new, even multiple filters:
systemtype:production
_search:true
nd:1358887847592
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"},{"field":"dow","op":"cn","data":"MO"}]}
I am using multipleSearch: true on the initial load. I'm pretty sure that's retained on reload
On the grid, the filtertoolbar retains my filter criteria, both text and selects, but when the grid reloads, the filters are ignored and the entire dataset is diplayed in the grid.
I've tried many examples posted here on SO. I've tried adding [{current:true}] to the reloadGrid call - no difference. I can't seem to retain and apply the filters on a reload.
I would like the reload to always return the full dataset from the server (which happens fine), and allow the current filter settings to control what is shown after the reload. I do not want to use the postdata to build a new SQL select statement - server side filtering, because at any time the user may want to click the pause button, select a new filter and view something else from the entire dataset without another reload.
$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-pause', onClickButton: function ()
{
clearInterval(stint);
},
title: 'End Auto Refresh'
});
How can this be done without using cookies, as I saw in one post?
I could try using jqGridExport'ing the postfilt var, and then jqGridImport'ing it but was hoping for a more direct approach. I'm not even sure this would help since I already have everything I need right here in the grid via postData.
As a side note, in my setGridParam above, the loadtext I specify is never displayed. Instead, the default "Loading..." is displayed. All of the other parameters are working.
Many thanks in advance,
Mike
Solution. The complete loadComplete to retain filters, sort index and sort order after a [json] reload from the server:
loadComplete: function() {
var $this = $(this);
postfilt = $this.jqGrid('getGridParam','postData').filters;
postsord = $this.jqGrid('getGridParam','postData').sord;
postsort = $this.jqGrid('getGridParam','postData').sidx;
if ($this.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$this.jqGrid("setGridParam", {
datatype: "local",
postData: {filters: postfilt, sord: postsord, sidx: postsort},
search: true
});
$this.trigger("reloadGrid");
}, 50);
}
}
Thanks very much!!!!
I only added a bit to your solution to retain the page number as well:
loadComplete: function () {
var $this = $(this);
var postfilt = $this.jqGrid('getGridParam', 'postData').filters;
var postsord = $this.jqGrid('getGridParam', 'postData').sord;
var postsort = $this.jqGrid('getGridParam', 'postData').sidx;
var postpage = $this.jqGrid('getGridParam', 'postData').page;
if ($this.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$this.jqGrid("setGridParam", {
datatype: "local",
postData: { filters: postfilt, sord: postsord, sidx: postsort },
search: true
});
$this.trigger("reloadGrid", [{ page: postpage}]);
}, 25);
}
}
I am not sure, but I suppose that the origin of your first problem could be mixing postData.filters and postData and usage filter property instead of filters``. You use
postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;
to get filter property instead of filters. You get undefined value. So the setting postData to postfilt means nothing.
The next problem is that the server response contains non-filtered data. To force filtering the data locally you have to reload the grid once after the loading from the server have finished. You can do this inside of loadComplete. Exactly here you can set postData.filter if required, set search: true and trigger reloadGrid event. It's important only to do this once to have no recursion and you must don't set datatype back to "json" in the case. The datatype will be changed to "local" and the end of loading from the server in case of usage loadonce: true option. If you want apply filtering locally you have to reload grid once with options datatype: "local", search: true and postData having filters specifying the filter which need by applied. See the code from the answer or another one which do another things, but the code which you need will be very close.
I want to remove a parameter from the store of a comboBox before it shows to the user, I know more or less how to do it but it´s not working properly, any one could give some solution? Maybe I need to select an specific event, but I tried with all the events that make sense and didn´t work, Here is the code:
var combo = fwk.ctrl.form.ComboBox({
storeConfig: {
url: app.bo.type.type_find
,fields: ['id', 'code']
}
,comboBoxConfig:{
triggerAction: 'all'
,allowBlank:false
}
});
combo.on('beforeshow', function() {
combo.store.removeAt(2);
});
Thank you very much!!!
Try removing it inside 'afterRender' event,
sample code:
listeners: {
'afterrender': function(comboRef) {
comboRef.store.removeAt(2);
}
}
Here you have the solution,
combo.getStore().load({
callback: function (r, options, success) {
if (success) {
combo.store.removeAt(2);
}
}
});
Is necessary to change it before the load of the store because first is painted the combobox and then is charged with the store data I was erasing data in a empty store.
We're working on a Kendo UI grid that is bound to REST endpoint. The messaging portion is working great.
Where we're having trouble is trying to mask a phone number input. We like the following behavior:
1) User clicks into phone number cell.
2) User enters 1234567890.
3) When leaving the cell, the format is changed to (123) 456-7890.
We looked already at custom formats. Those seem date/time and number specific. I haven't found a way to do a custom format for a string column.
We also looked at doing this with a formatPhoneNumber function that is called on each cell's change event. I'm not happy with that approach, though it does work.
Here is the base code for the grid. I'd like to just find a way to include a custom format, or bind to a function when defining the column or field properties.
EditGridConfig = function() {
var self = this;
self.gridConfig = {
columns: [
{ field: 'PhoneNumber', title: 'Phone Number', width: '150px' },
],
data: [],
toolbar: [
{ name: "save" },
{ name: "cancel" }
],
dataSource: {
type: "json",
transport: {
read: "/api/BusinessEntity",
update: {
url: function(parent) {
return "/api/BusinessEntity/" + parent.Id;
},
dataType: "json",
type: "PUT"
}
},
schema: {
model: {
id: "Id",
fields: {
PhoneNumber: { type: "string" },
}
}
}
},
editable: "incell"
};
self.selectedData = ko.observable();
};
Here is the change event and formatPhoneNumber function we are using to get the phone number to format when focus leaves the cell. I'm just not happy with this approach, and am looking for a "cleaner" way to do it.
change: function (e) {
if (e.field == "PhoneNumber") {
console.log('before' + e.items[0].PhoneNumber);
e.items[0].PhoneNumber = formatPhoneNumber(e.items[0].PhoneNumber);
console.log('after' + e.items[0].PhoneNumber);
}
}
function formatPhoneNumber(number) {
return number.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}
Thanks much for any suggestions!
Sorry for answering my own question. I thought I would add some more detail along the lines of #James McConnell's answer so other people won't struggle like I did trying to wire up the jQuery.on event with the .mask function.
Thanks to James' hint, I wound up using the Masked Input jQuery plugin and wiring up to dynamically created events using jQuery.on.
Here is the helper function I wrote (simplified for example):
applyDynamicInputMask = function(container, selector, event, mask) {
$(container).on(event, selector, function() {
var $this = $(this);
$this.mask(mask);
});
};
And to call it:
applyDynamicInputMask(document, "[name='PhoneNumber']", 'focusin', "(999) 999-9999");
edit: function (e) {
//if edit click
if (!e.model.isNew()) {
$('input[name=Time]').attr("data-role", "maskedtextbox").attr("data-mask", "00:00");
//init mask widget
kendo.init($('input[name=Time]'));
}
}
Have you tried a jQuery plugin? We use this one at work:
http://digitalbush.com/projects/masked-input-plugin/
You can bind the plugin to any jQuery selector, so just slap a custom class on the input that needs formatted, and use that to hook up the plugin. Not sure if this is a viable solution, but it's what I've used in the past. HTH! :)
I have a large HTML form that contains many fields that need an autocomplete for accounts. I tag these fields with the class AccountLookup and jQuery does the dirty work for the autocomplete:
$(".AccountLookup").autocomplete({
source: function (request, response) {
$.ajax({
url: "Lookup.asmx/GetAccounts",
data: "{ 'Search': '" + request.term + "' }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.Value
}
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
},
minLength: 3
});
Now, when a user selects something from the autocomplete I need it to populate a hidden field just BEFORE the tagged input field; probably using something like:
$(this).prev().val(item.Key);
How do I incorporate this functionality? Also, how do I force a user to select from the auto complete? (All the values are pre-defined, the user cannot add new ones.)
EDIT:
As far as I understand from inspecting the DOM, the select option is currently filling in the hidden form field.
select: function (event, ui) {
$(this).prev().val(ui.item.key);
}
I know this is an old post--- but I ran into it in trying to solve a similar problem (forcing the user to select an item from the list)...
$("#ac").autocomplete({
source: function (req, resp) {
//add code here...
},
select: function (e, ui) {
$(this).next().val(ui.item.id);
},
change: function (ev, ui) {
if (!ui.item)
$(this).val("");
}
});
$(".AccountLookup").autocomplete({
/*...*/
}).result(function(event, item) {
$(this).prev().val(item.Key);
});
You could also use a jQuery validate to ensure that the field is populated.
for force selection, you can use "change" event of Autocomplete
var availableTags = [
"ActionScript",
"AppleScript"
];
$("#tags").autocomplete({
source: availableTags,
change: function (event, ui) {
if(!ui.item){
//http://api.jqueryui.com/autocomplete/#event-change -
// The item selected from the menu, if any. Otherwise the property is null
//so clear the item for force selection
$("#tags").val("");
}
}
});
For the selection action, try using the formatItem option. You can format each result to have an onclick event that will populate the other textbox.
For the forcing to select from autocomplete, you need to use the mustMatch option.
http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions
I ran into this same problem quite awhile ago and some post helped me along with it. I have since modified the code as I found that there were cases I wanted one or more fields to fill in from the information returned. In the select option of the autocomplete I added a function.
select: function (e, ui) {ReSetField({'txtID':'id','txtPrice':'price' [,etc...]}, ui) }
The function "ResetFields" then takes in a JSON list of element names paired with fieldnames and uses the fieldnames to match the elements in the ui object. The value can then be pulled from the ui item and put into the html element.
function ReSetField(_flds, _vals) {
//Set up the flds to be reset with values passed in.
try {
if (_flds != undefined) {
if ($.type(_flds) == 'string') {
_flds = JSON.parse(_flds);
};
var _fld = null;
var _val = '';
$.each(_flds, function (index) {
if (index.length > 0) {
_fld = '#' + index; //Set the forms field name to set
_val = _flds[index]; //Pick up the field name to set the fields value
$fld = $(_fld);
$fld.val(_vals.item[_val]); //Set the fields value to the returned value
}
}
})
};
}
catch (e) {
alert('Cannot set field ' + _fld + '.');
}
}
By sticking the "fieldlist" into the HTML element as an attribute like "fieldlist" and using a class like "comboBox" I can then use a single function to find all ComboBox elements and set up the autocomplete on a form reducing the amount of code required to handle 2 or more lookups on a form.