Kendo Grid: How to change a field value in a template? - javascript

I'm using a kendo grid to display current values from a data source. Within the Kendo grid buttons are created to alter the values and display the change:
var grid = $("#Results").kendoGrid({
dataSource: resultsDS,
columns:
[{
title: "Drop Hammer",
field: "drop_hammer_bit",
width: 125,
filterable: false,
template: "<button type='button' class='btn pass-fail-btn' onclick='yes_btn_toggle($(this))'>#= drop_hammer_bit #</button>"
}]
}).data('kendoGrid');
function yes_btn_toggle(e) {
var txt = $(e).html();
if (txt == "No") {
$(e).removeClass('btn-secondary').addClass('btn-primary');
$(e).html("Yes");
$(e).value = "Yes";
} else {
$(e).removeClass('btn-primary').addClass('btn-secondary');
$(e).html("No");
}
}
There is a submit button which retrieves the Results data but it reflects data source and not the changes. I am struggling on understanding how to either A) correctly code the button click so that the submitted values are correctly or B) change how I can retrieve the altered data. So far my Submission function is this:
function submitQuality() {
var data = $("#Results").data();
var displayedData = $("#Results").data().kendoGrid.dataSource.view();
var cntr = displayedData.length;
var BatchQuality = new Array();
for (var i = 0; i < cntr; i++) {
var qualityObj = buildQuality(displayedData[i]);
BatchQuality.push(qualityObj);
}
}
Ultimately what I want to do is display the data source values of Yes/No and give the user the option to click a button to change its value. When they are ready they would click the Submit button to record the new changes. I feel like I am close to the answer but I lack the proper programming knowledge to weave it all syntactically.

I am not sure your requirement but i guess you are wondering to changed value yes to no and no to yes from kendo grid column button.
You will have to use refresh grid after changed value in the datasource.
$('#Results').data('kendoGrid').refresh()
Please let me know if code work for your.

Related

Custom function on table column reordering --> change underlying table model

I use SheetJS to upload an excel sheet to a ui.table. While uploading I add a technical ID to my column names, which I will need later on in my project. This is how I am adding the technical ID:
getColumnNames: function(worksheet, aData) {
var firstRow = aData[0];
var oColumns = [];
var cells = Object.keys(worksheet);
for (var i = 0; i < Object.keys(firstRow).length; i++) {
var columnName = Object.keys(firstRow)[i];
var technicalName = "COL" + ('0' + (i+1)).slice(-2);
oColumns.push({
columnId: columnName,
technicalId: technicalName
});
}
return oColumns;
},
When creating the Model, I bind both the columnId and the technicalId to each column.
My users should have the option to reorder the table columns in order to do a mapping to another table. (Context here is not really relevant) So basically there is another table below my uploaded table and a user should be able to reorder the columns of the "uploadTable" to match them with the table below.
Now in order to do a proper mapping, my technical ID has to be adjusted after the reordering is done. Therefore I'd like to add a function that's being executed after the user clicked a "refresh" button.
This function should adjust the technical columnNames. --> E.g. data gets uploaded, column on position 1 has the technical ID "COL01" now it gets dragged to position 2 --> technical ID should change to COL02 and vice versa.
I believe, the only way to do this is by accessing the DomRef of the table, because that's the only place where the actual current table structure is stored, but I'm not exactly sure how I would proceed.
My reordering function only gets the data so far:
onReorder : function() {
var table = this.getView().byId("uploadData");
var currentStructre = table.getDomRef();
},
I would appreciate any hints towards this. If anything is unclear, I'm happy to explain it!
sap.ui.table.Table allows its columns to be reordered by dragging and dropping, and the event columnMove is fired after.
One could keep track of and update some sequence label (e.g. ids) using an approach like this:
Remember ids (for example column label as id):
ids = oTable.getColumns().map(oColumn => oColumn.getAggregation('label').getText())
Update ids:
oTable.attachColumnMove(function(oEvent) {
var from = oEvent.getParameter('column').getIndex();
var to = oEvent.getParameter('newPos');
var name = names.splice(from, 1);
names.splice(to, 0, name);
// Then write new ids to model;
})

jQuery Datatable, Outputting values of textboxes to selected row's columns

I currently have a jQuery Datatable, which upon a row being clicked on, the data from that row is outputted to textboxes and select boxes. I'm trying to make it so whatever is entered into the textboxes, will be saved/entered into the selected row upon pressing the saverow button.
Here's my JSFiddle: JSFiddle
Javascript:
var table = $('#example').DataTable();
(function () {
var table = document.querySelector('#example');
var name = document.querySelector('#nameinput');
var format = document.querySelector('#formatinput');
var address = document.querySelector('#addressinput');
var report = document.querySelector('#reportinput');
var alarm = document.querySelector('#alarminput');
table.addEventListener('click', onTableClick);
function onTableClick (e) {
var tr = e.target.parentElement;
var data = [];
for (var td of tr.children) {
data.push(td.innerHTML);
}
name.value = data[0];
address.value = data[1];
format.value = data[2];
report.value = data[3];
alarm.value = data[4];
console.log(alarm.value);
}
$("#saverow").click(function() {
var table1 = $('#data-table').DataTable();
var data = [];
data[0] = name.value;
data[4] = alarm.value;
console.log(name.value);
console.log(alarm.value);
table1.draw(true);
});
})();`
With the saverow code, I thought by trying to make the columns equal to the value of the textbox, then redrawing the table would work. The console does have the correct output when you type something new into the textbox then pressing Save. I just cant figure out how to put that back into the selected row.
I'm not wanting to do the inline editing if possible. Trying to keep it in this format.
I don't know if this counts as an answer, but you're not actually doing anything with that data variable in the save row click. You take the datatable, do nothing to change it, and then redraw it. So it's not surprising nothing is happening.
See this change to your fiddle to get the rows adding:
https://jsfiddle.net/o92g9goL/14/
Primarily, you need to set the table and datatable into different arrays. Also do it inside the main function. Also you need to actually add this code:
datatable.row.add(data).draw(false);
As for the editing, you'll need to make sure that you don't just prepopulate it, but make an actual reference to that row, otherwise how will it know to update it?

AngularJS -- RZSlider update stepsArray

I'm trying to edit the rz-slider's labels that appear below the ticks. I am able to obtain the values and everything but if I try to update the stepsArray to the rzslider, it is not being updated. I couldn't find anything on how to update the legend values like this. I feel like I need to reinitialize or refresh the slider in some way but the refresh slider code as shown in https://github.com/angular-slider/angularjs-slider did not work:
vm.refreshSlider = function () {
$timeout(function () {
$scope.$broadcast('rzSliderForceRender');
});
};
The code that I am using is as follows. Currently the existing legend contains the word "Text" and I am just trying to check if I can update it to the numeric values just to check if it works but it isn't:
if(vm.legend != ""){
var stepCount = $("#stepCount").val();
vm.priceSlider.options.stepsArray = [];
for(var i = 1; i <= stepCount; i++){
vm.priceSlider.options.stepsArray.push({
value: i,
legend: i.toString()
});
}
vm.refreshSlider();
}
I am kinda new to angular and this is my first time working with the rzslider as well, so any help would be appreciated. Thank you.

Conditionally expand row in kendo grid

In my Kendo grid, I am trying to check if one of my column fields is true or false. If it is true, row should be expanded, if it is false, row should stay collapsed. My code definition for column is:
{
field: "Comment",
title: txt.TXT_COMMENT,
template: '<input type="checkbox" #= Comment ? "checked" : "" # disabled="false" ></input>',
},
My code condition in dataBound for checking if there is data:
dataBound: function (e) {
var data = this.dataItem;
if (data.Comment == 1) {
this.expandRow(this.tbody.find("tr.k-master-row"));
}
f_OnDataBound(e);
}
Thanks for your help!
You are on the right direction by using the databound event. What you need to do after it is, iterating through all the rows and check for a specific model property and expand, or not, that specific row.
var grid = $("#grid").data("kendoGrid");
var data = grid.dataSource.data();
var len = data.length;
for(var i = 0; i < len; i++) {
var row = data[i];
if(row.Comment == '1') { // checks for the value of the Comment property
grid.expandRow("tr[data-uid='" + row.uid + "']"); // expands the row with the specific uid
}
}
I tested this and works perfectly. I can't know what's on the Comment propery though, that's up to you to control and adapt the javascript function if needed.
EDIT
I have created a fiddle that demonstrates the above strategy. In the example the dataBound function looks for the property "name" and expands the row if it is "Sally"

How do we implement a cancel in plain Javascript?

I have a page and I display data in a table.
In each table I have a column with a checkbox which if is checked the user can modify the specific row via Javascript.
This is done as its td encapsulates either an input or a select and I make these editable for the user.
The user modifies the row and presses save and the changes are saved. So far ok.
My problem is how do I implement a cancel?
The user could choose many row i.e. check boxes and modify them but the user could also press cancel. On cancel the original values should be displayed (and the rows become non-editable again).
But how is a cancel operation implemented in Javascript? Do we store data in some global datastructures? Which would be this in Javascript?
Ok, after the addition of informations you provided I suggest you setup the following mecanism:
function getDatas() {
var oXhr;
//get datas from database:
oXhr = new XMLHttpRequest();
oXhr.onreadystatechange = function() {
if (oXhr.readyState == 4 && (oXhr.status == 200)) {
g_oData = (new DOMParser()).parseFromString(oXhr.responseText, "text/xml");
}
}
oXhr.open("POST", "yourphpscriptthatreturnsthexmldatas.php", true);
oXhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
oXhr.send();
}
function populateGrid() {
//use g_oData to populate your grid, but at first totally clean the body
var mygrid = document.getElementById("mygridid");
//mygrid.innerHtml = "<table><tr><td>...</td></tr></table>";
//use the xml library to parse g_oData and fill up the table:
var xmlRows = g_oData.getElementsByTagName("TAG");
var xmlRow;
iLen = xmlRows.length;
for (var i=0;i<iLen;i++) {
xmlRow = xmlRows[i];
//use xmlRow->textContent to build each cell of your table
}
}
function revertChange() {
//on cancel, revert the changes by populating the grid.
//it will use the global xml/json object loaded directly from database, to refill everything.
populateGrid();
}
I did it myself many times to refresh some datas in a page. That's basically what you're doing except that you're not requesting anything to the database, you just refill the fields.
You can just access the original value attribute of the input to get the defaultValue. Sample implementation:
$("table").on("dblclick", "td", function(e) {
var val = $(this).html();
$(this).empty().append($("<form/>").append(
$("<input/>", {type:"text"}).attr("value", val),
// ^^^^
// set the *attribute*, as if it was present in the parsed HTML
$("<button/>", {type:"reset"}).text("Reset"),
$("<button/>", {type:"button", class:"cancel"}).text("Cancel"),
$("<button/>", {type:"submit"}).text("Submit")
));
}).on("submit", "form", function(e) {
var val = $(this).find("input:text").val();
// ^^^^^
// which is equivalent to .prop("value")
/* then do something with val, e.g. send it to server via ajax */
$(this).parent().html(val);
e.preventDefault();
}).on("click", "button.cancel", function(e) {
var $form = $(this).parent(),
$input = $form.find("input:text"),
oldval = $input.attr("value");
// ^^^^^^^^^^^^^
// or .prop("defaultValue"), but not .val()!
if (oldval == $input.val() || confirm("Do you really want to discard your changes?"))
$(this).parent().html(oldval);
e.preventDefault();
});
(Demo at jsfiddle.net)
A maybe more simple solution might be to use the dblclick-handler that creates the form as a closure and just store the original html in a local variable there.
Here is a pretty simple way:
Don't replace the cell content with the form element. Keep the value (the text) in a span element and hide it when you show the form element. Then you don't have to do anything on cancel. Just show the span again and hide or remove the form element. Only update the span when the user wants to save the value.
Here is an example. The showing and hiding is all done with CSS.
<tr>
<td>
<span>value</span>
<input type='text' value='' />
</td>
<td>
<button class="save">Save</button>
<button class="revert">Revert</button>
</td>
</tr>
JS:
var rows = document.querySelectorAll('table tr');
for(var i = 0, l = rows.length; i < l; i++) {
rows[i].addEventListener('click', function(event) {
// all value display elements in the row
var spans = this.querySelectorAll('span');
// all form elements in the row
var inputs = this.querySelectorAll('input');
// handle click on save button
if (event.target.className === 'save') {
[].forEach.call(inputs, function(input, i) {
spans[i].innerHTML = input.value;
});
this.className = '';
}
// handle click on revert button
else if (event.target.className === 'revert') {
// not much to do
this.className = '';
}
else {
// update form element values
[].forEach.call(inputs, function(input, i) {
input.value = spans[i].innerHTML;
});
this.className = 'edit';
}
});
}
DEMO
You can use the HTML5 data- attributes to implement a revert function. This way, each <input> would hold it's original value in case a revert button would be used.
Here's how it'd look:
<table>
<tr>
<td><input type='text' value='change me' data-original='change me' /></td>
<td><input type='text' value='change me2' data-original='change me2' /></td>
<td><input type='button' value='revert' onclick='revert(this)'/></td>
</tr>
<table>
And the code that reverts:
function revert(btn) {
var parentTr = btn.parentNode.parentNode;
var inputs = parentTr.getElementsByTagName('input');
for(var i = 0; i < inputs.length; i++) {
if (inputs[i].type == 'text') {
inputs[i].value = inputs[i].getAttribute('data-original');
}
}
}
The data-original attribute could be generated:
By the server-side app who serves the page (see (1) demo fiddle here); or
by a JavaScript function that is executed as soon as the DOM is ready (see (2) demo fiddle for this here).
As a side solution, you could store the original values in a map object. Here's the (3) demo for this (notice I added the id for each input, so it can be used as key to the map).
Keep in mind, though, neither solutions (2) or (3) require changing in server side code (the 3 assuming your inputs have ids). And (2) feels clearer.
About the defaultValue attribute: The defaultValue attribute can be a solution only if the value to be reverted never changes and if the fields involved are text inputs.
Firstly, changing the "default value" is rather awkward and may break something else aling the page (one would expect the browsers make the defaultValue attribute read-only, but that does not seem to be the case). Secondly, you would be limited to inputs of the text type.
Still, if none of that is a problem, the code above can be quickly adapted to use them instead of data- attributes.

Categories