jqGrid: format cell value without changing actual (underlying) value? - javascript

Is that possible to display something other, yet keeping the original cell value for editing purposes?
one of the columns in my jqGrid is 'enumerated' data. For editing I'm providing edittype: select + editoptions: enum-key:label set, which results in properly displayed select editor. However I'd like to display the label instead of enum-key for regular view, not only editing. I know I could use custom cell formatters but that would cause the actual value to be changed, then I'd have to lookup the keys-labels pairs again before editing the row...

It's hard to say without seeing some code, but you shouldn't need to use a custom formatter, just use formatter: 'select' as shown in the documentation. It specifically states that "the data should contain the keys (“1” or “2”), but the value (“One”, or “Two”) will be displayed in the grid".
Another option if you need more control over the output is to use the buildSelect option of editoptions. For example, here is a select that I have in code, there are other examples out there too. The idea of course is that you can return any data and then manipulate it as needed to build the select. The data event change function then makes sure that the correct value is set for the input field.
{ name: 'Id', index: 'Id', editable: true, hidden: true,
editoptions: { defaultValue: row_id,
dataUrl: "DataService.asmx/GetList",
buildSelect: function (data) {
var s = '<select>';
if (data && data.d) {
//data is nested, so we need a few steps to get to the actual data
var list = data.d;
var opts = JSON.parse(list);
var subList = opts.List;
//loop through the data to build the options list
for (var i = 0, l = subList.length; i < l; i++)
{ var ri = subList[i];
s += '<option value=' + ri.Id + '>' + ri.Name + '</option>';
}
}
else {
s+= "<option value=0>No data to display</option>";
}
return s + "</select>";
} ,
dataEvents: [
{ type: 'change',
fn: function (e) {
$('input#Id').val(this.value);
}
}
]
},
editrules: {edithidden: true},
edittype: 'select'
}

Related

Dynamically set select2 options with formatting

Select2 v4.0 lets you add options to the dropdown dynamically by creating new Option objects and appending them. How can you dynamically add data which has more than just an id and text?
More specifically, if the select2 uses the templateResult configuration to style data with more than just plain text then adding Options is too restrictive. This callback only works with the library's own data format.
$('#select2').select2({
templateResult: function(data) {
return data.text + ' - ' + data.count;
}
});
$('#select2').append(new Option('Item', 1, false, false));
I'd like to add more complex data when the dropdown is opened and template the results.
I've tried some ugly workarounds, such as
var opt = new Option('Item', 1, false, false);
opt.innerHTML = '<div>Item</div><div>Count</div>';
But the HTML gets stripped and select2 displays plain text.
The library's maintainer states there is not going to be any support for this feature, as reported in a closed Github issue . The only reasonable workaround I've found is to re-initialize the element after it's populated:
function initSelect2(data) {
var select = $('#select2');
select.select2({
templateResult: function(data) {
return data.text + ' - ' + data.count;
});
if (data.length) {
select.data('loaded', 1);
select.select2('open');
} else {
select.on('select2.opening', fillSelect2);
}
function fillSelect2() {
var select = $('#select2');
if (select.data('loaded')) {
return;
}
var data = [];
var data.push({id: 1, text: 'One', count: 1});
var data.push({id: 2, text: 'Two', count: 2});
var data.push({id: 3, text: 'One', count: 3});
initSelect2(data);
}
initSelect2();
Maybe just using the standard html/jQuery and customize whatever you need.
$('#select2').append("<option value='"+ id +"'>" + text+ "</option>");

Edit button for each DataTable row, can't pass data

I have a DataTable called Branches which has three columns: Name, Code and Email (along with an ID column hidden to users). It originally has an Edit button on top, and only after clicking on a row can the user click on the button to open a dialog box with the fields populated and edit them. Now however I need to change it so that each row has its own Edit button, therefore removing the need to click on the row first.
So now I have an Edit button for each row in a DataTable, but I can't pass the data for that particular row besides the Index number. The relevant blocks of code are below (unless I missed something, please tell me if I have):
var txtName2 = $("#txtName2"); //For Update
var txtCode2 = $("#txtCode2");
var txtEmail2 = $("#txtEmail2");
var dialog;
var tblBranch = $("#tblBranches");
var branchList;
var selectedIndex;
branchList = response.branches;
var data = { "aaData": [] };
$.each(response.branches, function (i, item) {
data.aaData.push({
"id": item.id,
"name": item.name,
"code": item.code,
"email": item.email,
"action": "<button> class='btnUpdate' type='button' onClick='testUpdateButton(" + i + ")'</button>"
});
});
function testUpdateButton(index, name, code, email) {
//alert(index);
selectedIndex = tblBranch.row(this).index();
var selectedName = tblBranch.row(index).name;
var selectedCode = tblBranch.row(index).code;
var selectedEmail = tblBranch.row(index).email;
//alert(name);
onBtnUpdateClicked(index, name, code, email);
}
function onBtnUpdateClicked(index, name, code, email) {
if (branchList != null && branchList.length > 0) {
var selectedItem = branchList[selectedIndex];
txtName2.val(selectedItem.name);
txtCode2.val(selectedItem.code);
txtEmail2.val(selectedItem.email);
dialog = $("#dialog-form-update").dialog("open");
}
}
When I only pass in the index number 'i' at the button and not the name, code or email, the alert(index) under testUpdateButton displays the correct index number of the selected row, therefore confirming it can get the index number, but not the other three columns (the alert(name) displays nothing).
So I've tried passing all four fields at the button like such:
"action": "<button> class='btnUpdate' type='button' onClick='testUpdateButton(" + i + ", " + item.name + ", " + item.code + ", " + item.email + ")'</button>"
but it only gives me an error: "Uncaught SyntaxError: missing ) after argument list" when I inspect the page in Chrome. I can't see where the missing bracket should be.
Basically, I can obtain the index number but cannot use it to get the corresponding name, code and email.
For reference, here is the function that's the closest thing to a solution I had earlier - this would pass all the row data and load the Editing dialog box with the input fields populated whenever I clicked anywhere on the row itself. It was modified from the previous "Click on row first" version, though I merely added the onBtnUpdateClicked function. Not ideal, but at least it did what it should.
$("#tblBranches tbody").on('click', 'tr', function () {
selectedIndex = tblBranch.row(this).index();
onBtnUpdateClicked();
});
Any help is much appreciated.
Since you are able to get the index of row, you can use this to get other values. Try something like this
function testUpdateButton(index){
//alert(index);
selectedIndex = index;
var name=$("table tr").eq(index).children('td').eq(1).text();
var email=$("table tr").eq(index).children('td').eq(2).text();
alert(name);
alert(email);
onBtnUpdateClicked(index, name, email);
}
A woorking fiddle to get these values is https://jsfiddle.net/shoaibakhter/atpgdofh/19/. This is not a complete solution, but yes this will help you to get other values, which you can pass in your onBtnUpdateClicked function. You have to change the functions as per your table structure and in your onBtnUpdateClicked use these values as below-
function onBtnUpdateClicked(index, name, email) {
if (branchList != null && branchList.length > 0) {
var selectedItem = branchList[index];
txtName2.val(name);
txtEmail2.val(email);
dialog = $("#dialog-form-update").dialog("open");
}
}
Hope this will help you.

JQuery Datatable rows not deleting despite on calling clear function

Im trying to remove all the rows in jquery data tables when new data arrives in order to fill with new rows.
But the problem is despite calling clear function it simply add the result rows to previous rows.
How to clear the rows in jquery data tables . Following is the code
var table = $("#editable");
var tp = table.DataTable({
"paging": true,
"createdRow": function (row, data, index) {
$compile(row)($scope);
}
});
//more code here ajax call only from angular post
if (result != null) {
$scope.reviews = result;
$window.toastr["success"]("Loaded Successfully !", "Recent Reviews");
tp.clear().draw();
for (var i = 0; i < $scope.reviews.length; i++) {
var id = $scope.reviews[i].ID;
var checked = $scope.reviews[i].Enabled == "1" ? true : false;
tp.row.add([
$scope.reviews[i].ID,
$scope.reviews[i].AddedOn,
$scope.reviews[i].Company.Name,
$scope.reviews[i].Rate,
$scope.reviews[i].User.Name,
$scope.reviews[i].Description,
"<div class='switch'><div class='onoffswitch'><input ng-model='$scope.reviews[" + i + "].Enabled' ng-click='ChangeReviewPublishStatus(" + $scope.reviews[i].ID + ")' ng-checked='" + checked + "' class='onoffswitch-checkbox' id= 'stat" + id + "' type= 'checkbox'><label class='onoffswitch-label' for='stat" + id + "'><span class='onoffswitch-inner'></span><span class='onoffswitch-switch'></span></label></div></div>"
]).draw();
}
}
I would place that piece of code inside a $timeout. Both dataTables and angular wants to manipulate the DOM - angular wins the battle and by that dataTables never get a chance to finish its business. A $timeout will force the dataTables clear() and data population into the next digest, and ensure it is actually executed.
$timeout(function() {
tp.clear().draw();
for (var i = 0; i < $scope.reviews.length; i++) {
var id = $scope.reviews[i].ID;
var checked = $scope.reviews[i].Enabled == "1" ? true : false;
tp.row.add([
$scope.reviews[i].ID,
$scope.reviews[i].AddedOn,
//etc
]).draw();
}
});
Well, that is at least my theory - cannot replicate your scenario in full - let me know if it makes any difference.

Adding a working select element to an existing table

I have a JavaScript function that adds a new row to a table. It works absolutely fine adding data types such as input (text), textbox, and radio. It also works using
document.createElement('select');
but as soon as I try to add elements, the button that triggers the JS function does nothing, which I assume means there's an error but I don't get any indication of what the problem is. I'm sure I've just missed something simple but it's been holding me back for hours and it's driving me insane!
The main body of the function is fine, because any other data type creates and adds itself to the table cell accordingly. An example of JS that works correctly within the function:
// inner left cell - text input
var cellTwo = row.insertCell(1);
var el = document.createElement('input');
el.type = 'text';
el.name = 'col' + rowNumber;
el.id = 'col' + rowNumber;
cellTwo.appendChild(el);
The code to try and create a select element with working options: (N.B. this works if I comment out the options part and simply create an empty select element, so the error MUST be somewhere within the foor loop and must just be a result of my misunderstanding how to create options dynamically:
// inner right cell - select box
var cellThree = row.insertCell(2);
//create select element
var dropDown = document.createElement('select');
//give select element id and name
dropDown.id = 'fieldtypecol' + rowNumber;
dropDown.name = 'fieldtypecol' + rowNumber;
//declare array values to put in option elements
var optionValue[] = new Array('varchar(255)', 'int', 'date', 'float(53)');
var optionText[] = new Array('String', 'Integer', 'Date', 'Float');
//declare option element holder
var option;
//loop through creating and adding values to options
for (var i = 0; i < 4; i++)
{
option = document.createElement('option');
option.value = optionValue[i];
option.text = optionText[i];
//append current option before loop restarts
dropDown.appendChild(option);
}
//append select element to new table cell
cellThree.appendChild(dropDown);
Any help would be much appreciated, thanks.
It appears in your codes the lines;
var optionValue[] = new Array('varchar(255)', 'int', 'date', 'float(53)');
var optionText[] = new Array('String', 'Integer', 'Date', 'Float');
Should be;
var optionValue = new Array('varchar(255)', 'int', 'date', 'float(53)');
var optionText = new Array('String', 'Integer', 'Date', 'Float');
Types are dynamic in JS, I would have thought these errors would appear in the JS console for you.

Need help understanding jQuery .val() function

alert("data going into $hidden: " + selected.data[1]);
hidden.val(selected.data[1]);
alert("data now in $hidden: " + $hidden.val());
What would be a reason that $hidden.val() in the last line above would return undefined? I have verified that selected.data[1] contains an integer value.
Edit #1: Some additional context per comments: ($hidden is a hidden input field)
$.fn.extend({
autocomplete: function(urlOrData, hidden, options) {
var isUrl = typeof urlOrData == "string";
var $hidden = $(hidden);
options = $.extend({}, $.Autocompleter.defaults, {
url: isUrl ? urlOrData : null,
data: isUrl ? null : urlOrData,
delay: isUrl ? $.Autocompleter.defaults.delay : 10,
max: options && !options.scroll ? 10 : 150
}, options);
// if highlight is set to false, replace it with a do-nothing function
options.highlight = options.highlight || function(value) { return value; };
// if the formatMatch option is not specified, then use formatItem for backwards compatibility
options.formatMatch = options.formatMatch || options.formatItem;
return this.each(function() {
new $.Autocompleter(this, options, $hidden);
});
and...
$.Autocompleter = function(input, options, $hidden) {
//...
function selectCurrent() {
var selected = select.selected();
if (!selected)
return false;
var v = selected.result;
previousValue = v;
if (options.multiple) {
var words = trimWords($input.val());
if (words.length > 1) {
v = words.slice(0, words.length - 1).join(options.multipleSeparator) + options.multipleSeparator + v;
}
v += options.multipleSeparator;
}
alert("data going into $hidden: " + selected.data[1]);
$hidden.val(selected.data[1]);
alert("data now in $hidden: " + $hidden.val());
Edit #2: More details.... I'm trying to use the jQuery autocomplete extension on a form with multiple textbox controls (each implement the autocomplete). There's a seperate button on the form beside each textbox that submits the form to a handler function that needs to find the value of the item selected and save it to the db. The way I thought to go about this was to include a hidden field on the form to hold the selected value.
Thanks Paolo Bergantino. I discovered that I wasn't passing the initial hidden in with a # in front of the hidden field id, so $hidden was never getting set properly. It was difficult for me to debug because the the autocomplete is inside an ascx control as an embedded resource. Once I ensured that the value of hidden was including the # it worked properly.
Could $hidden be a checkbox that is not checked?

Categories

Resources