How can I edit table row using JavaScript querySelector()? - javascript

I am trying to edit data from a table. When the edit button is pressed it will bring up an input field to edit the new value in the selected row, I tried using the code below, but nothing changes when I press the edit button.
Here is my code:
const editRow = (index = "x") => {
const tdTable = document.querySelectorAll("table > tbody > tr");
const newRow = `
<tr>
<td>
<input type="text" name="name" />
</td>
<td>
<input type="text" name="umur" />
</td>
<td>
<input type="text" name="address" />
</td>
<td colspan = 2>
<span class="btn btn-info" onClick="saveData()">Save</span>
</td>
</tr>`;
tdTable.innerHTML = newRow;
};
Here is what the table looks like in the browser when I press the edit button.

You need to do something to actually put the input values back into the original <td>s. Below I prepared an MCVE (minimal complete and viable example), showing how it can be done:
const tb=document.querySelector("tbody"), edidel="<button>Edit</button> <button>Delete</button>";
// prepare the page first (fill in some sample data):
tb.innerHTML= [[1,"jansen",35,"medan"],
[2,"Alfa",31,"jakarta"],
[3,"joko",10,"solo"],
[4,"eko cahyonto",20,"NTB"]].map(r=>
"<tr><td>"+r.join("</td><td>")+"</td><td>"+edidel+"</td></tr>" ).join("\n");
tb.onclick=ev=>{
[...ev.target.closest("tr").children].forEach((td,i)=>{ const btn=ev.target.textContent;
if (btn==="Edit")
td.innerHTML=i<4?'<input type="text" value="'+td.textContent+'" data-orig="'+td.textContent+'">'
:'<button>Save</button> <button>Cancel</button>';
else if (["Save","Cancel"].includes(btn))
td.innerHTML=i<4?(btn==="Save"?td.children[0].value:td.children[0].dataset.orig)
:edidel;
})
}
input {width:50px}
<table>
<thead><tr><th>No</th><th>Nama</th><th>Umur</th><th>Alamat</th><th>CRUD</th></thead>
<tbody></tbody>
</table>
The first 7 lines of code simply prepare a small table on which we can work. The actual script then starts with a "delegated click event attachment" on the first <tbody> element of the page (which happens to be our test table). This means, we can add or remove table records and don't have to worry about attaching events to the newly created buton elements any more.
An action will only happen, if the clicked element has an ยด.textContent` of either "Edit", "Save" or "Cancel" (an action for the "Delete" button has not yet been defined but can easily be added).
Depending on the actual clicked button some action on the <TD> elements directly before the button will be performed:
when going into "Edit"-mode the td.textContent of each <td> is copied into a newly created <input type="text"> element and is also save in its data-orig attribute, in case we want to click on "Cancel" later on.
"Save" will copy the .value of each <td>s first child (the <input> element) back to its parent td.innerHTML attribute.
in case "Cancel" was clicked, the <input>'s .dataset.orig value is put back into the td.innerHTML attribute.

JavaScript is a case-sensitive language.
try fixing the uppercase onClick to onclick, as the example: <button onclick="myFunction()">Click me</button>

Related

How to conditionally change column to textbox in AngularJS grid?

I want to know how to add one particular column value as textbox in an AngularJS grid.
So, I am implementing an AngularJS grid as below:
<div>
<table>
<tr>
<th>
<td>Customer Account Number</td>
<td>Customer Name</td>
</th>
</tr>
<tbody>
<tr ng-repeat="item in data">
<td>{{item.CustomerAccNumber}}</td>
<td>{{item.CustomerName}}</td>
</tr>
</tbody>
</table>
<input type=button value="Add Row" ng-click="Add()"/>
So, in scenario 2 things happen:
By default I am getting few records as "Customer Account Number" and "Customer Name".
But there is an "Add Row" button on the same page I need to implement which adds a new row to the grid.
The first column "Customer Account Number" is a text box and second row is noneditable.
So, how to place textbox as a column only when adding a new row from button?
Let's say after adding add row my first column is coming as text box, so after entering the account number in the textbox on textchange it should fetch the customer account number and display it in the same row.
Can someone help me figure out how to put the textbox into one particular column in grid?
Can it be done the way I have implemented the grid?
I don't want to use nggrid.
I would do something like this:
First, in your Controller, in your Add() function, when you push a new row, add a field such as isEditable to allow you to differentiate between a newly added row in the UI.
$scope.Add = function() {
$scope.data.push({
'CustomerAccNumber': 1,
'CustomerName': '',
'isEditable': true // field to identify new row
})
}
Then in your markup, having that flg available, you can leverage ngIf, like so:
<tr ng-repeat="item in data">
<td ng-if="!item.isEditable">{{item.CustomerAccNumber}}</td>
<td ng-if="item.isEditable">
<input type="text" ng-model="item.CustomerAccNumber">
</td>
<td>{{item.CustomerName}}</td>
</tr>
it should fetch CustomerAccount number
As far as your third item, you can use ngBlur to make a call when the user clicks out of the box:
1) Define a function in your controller to call when the user leaves the box.
$scope.doSomethingWithAccNumber() {
// $http call, etc
}
2) Update your textbox to use the ngBlur directive that will trigger when the user clicks out.
<td ng-if="item.isEditable">
<input type="text"
ng-model="item.CustomerAccNumber"
ng-blur="doSomethingWithAccNumber()">
</td>
If you want other keys to trigger this, you can use ngKeydown as well. Use of this is outlined well here. For example, you would want to add ng-keydown="$event.keyCode === 13 && doSomethingWithAccNumber()" to your input to trigger on Enter.

Unable to uncheck checkbox from chrome

I am trying to check/uncheck a checkbox/radiobutton both from the table cell as well as the actual checkbox /radiobutton
I have written this below code to select a checkbox/radiobutton from table cell
Please refer code pen for actuall code.
The code works fine for IE 11 browser but not in Chrome. If i select the table cell then the checkbox is selected but in chrome when i check on the actual check box nothing happens .
I think it is the checkbox internally calls the PropagateBelow method.
Check/Uncheck check box for chrome(Select on the CHECKBOX itself on TABLE CELL works fine)
<table border="1">
<tr>
<td onclick="PropagateBelow(this);" style="width:100px;">
<input type="checkbox" id="test" value="Test123" />
</td>
</tr>
function PropagateBelow(tableCell) {
alert(tableCell);
var radioButtons = tableCell.getElementsByTagName('input');
for (var i = 0; i < radioButtons.length; i++) {
var radioButton = radioButtons[i];
if (radioButton != null && radioButton != undefined) {
if (radioButton.type == 'radio' || radioButton.type == 'checkbox') {
radioButton.click();
}
}
}
}
Not quite sure what the exact misbehavior is you're observing. What happens when I test your code is that when clicking the cell, PropagateBelow(this) is called which activates/deactivates the checkbox, based on its current state. When I click the checkbox, the checkbox is ticked, but then the click event bubbles up, again triggering PropagateBelow(this) which in turn unticks the checkbox again.
If you want to prevent that, you have to stop the propagation of the event when you click on the checkbox, like
<table border="1">
<tr>
<td onclick="PropagateBelow(this);" style="width:100px;">
<input type="checkbox" id="test" value="Test123" onclick="cancelPropagation();" />
</td>
</tr>
</table>
and then implement cancelPropagation() as follows
function cancelPropagation(ev){
var event = ev || window.event;
event.stopPropagation();
return false;
}
Here's your modified codepen project: http://codepen.io/anon/pen/MwEpxm
As mentioned, I'm not sure I got what you mean. If this doesn't help, let me know, so I'll delete my answer again :)
Instead of using a JavaScript function to propagate the click to all of the radio buttons, you can wrap the radio button in label which takes up the whole space of the table cell. Wrapping a radio button in a label will allow you to click anywhere in the label to toggle the radio button without having to use any JavaScript.
Please see example here: http://codepen.io/anon/pen/GJMWzb
<table border="1">
<tr>
<td style="width:100px;">
<label style="width:100%;height:100%;display:block;">
<input type="checkbox" id="test" value="Test123" />
</label>
</td>
</tr>
</table>
Funnily enough this does work fine for me in Chrome, but as a general rule it's better to set the checked property to true on checkboxes instead of trying to simulate clicks.
This could simply be done by replacing radioButton.click(); with radioButton.checked = true;, or if you wanted to toggle the checkbox radioButton.checked = !radioButton.checked;.
https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Attribute/checked

Textbox that is added dynamically to table is behaving like readonly field

I have table with row expand option. On row expand adding one more table row with cell and appending textbox to the same cell using jquery. This is working fine, but textbox that is added dynamically is behaving like readonly field. Please let me know the solution for the same.
<table>
<tr><td> href field here</td><td></td><td></td></tr>
</table>
on click of href field adding row with one cell and textbox in it
<tr><td colspan=3 id="test-cell"></td></tr>
After appending this to table appending textbox to cell with id "test-cell"
$('#test-cell').append('<input type="text" size="10" value="abd" id="test-input" />');
Finally table becomes
<table>
<tr><td> href field here</td><td></td><td></td></tr>
<tr><td colspan=3 id="test-cell"><input type="text" size="10" value="abd" id="test-input" /></td></tr>
</table>
Tested same code in Chrome, FF, IE 11.
Code that I am using for the same (I extracted this code and replaced generic variable with hard code)
var table = $('#C1tbl');
var selectedRow = table.find('tbody>tr.grid-row:eq(2)');
var expandRow = $('<tr class="ag-row-expand"><td colspan="3" id="test-cell"></td></tr>');
expandRow.attr('id', Util.getNextComponentId());
selectedRow.after(expandRow);
var expandCol = expandRow.find('>td');
expandCol.html('<input type="text" size="10" value="abd" id="test-input" />');
After this my web page is not allowing to edit the text.
Probably you can use $('#test-cell').after().html('< input type="text" size="10" id="test-input" />')
This is my mistake only. Table has keydown event to havigate across the rows using navigation keys where function is calling event.preventDefault for all the keys.

Removing duplicates and not valid entries from a select box, but not refreshing the whole box

I'm trying to write a web form, which will have selectable options based on users input from earlier in the form.
Where I'm getting stuck is;
I have a table room types, which is just td tags with input tags (type=text). These are filled in by a user, so I've no idea what they are..
I've got a button to add extra lines to this table (Jquery to add another td tag and input tag)
Users add as many lines as needed
The next part of the form is to fill in Rooms, and select the type for each room. The table layout is the same (except there are two columns, rather than one), and extra lines are added via another button with Jquery.
What I'd like to be able to do, is for new lines added to have two columns in the table. One input text field, and the other a select box with options taken from the table above.
I've managed to get this working to a point. But as users may go back to edit options from the original (room types) table, I need the select boxes to adjust their values based on what the original table currently says.
I can get this working by emptying and re-populating my select boxes everytime one of the input fields accessed (using OnBlur, which is probably not the most effective way to do this), but since it removes entries from the bxes, and then re-populates, any of the select boxes that have been populated already get reset. I only want invalid options (i.e. values that do not exist in the original table) to be reset.
I've been looking/playing at this for a long time now, but my programming abilities are only what I've taught from here and google, whilst messing around on a few very small things before...
My HTML code as it stands (well, part of my code, I've removed all the irrelevant code to keep it simple) is here:
<div id="rm_types_info">
<table id="room_types_table">
<tr>
<td><input type="text" class="room_types" onblur="edit_rooms_select();" /></td>
</tr>
</table>
<button type="button" onclick="rmtypes('room_types_table');">Add Another Room Type</button>
</div>
<div id="rooms_info">
<table id="rooms_table">
<tr>
<th>Room Number</th>
<th>Room Type</th>
</tr>
<tr>
<td><input type="text" /></td>
<td>
<select class="room_type_select">
<option value="Please Choose">Please Choose</option>
</select>
</td>
</tr>
</table>
<button type="button" onclick="rooms('rooms_table');">Add Another Room</button>
</div>
and my JQuery is;
<script>
var userscounter=2
var rmtypescounter=1
var roomscounter=2
function users(ID){
document.getElementById(ID).insertRow(userscounter).innerHTML = '<td><input type="text" /></td><td><input type="text" /></td>';
userscounter++;
};
function rmtypes(ID){
document.getElementById(ID).insertRow(rmtypescounter).innerHTML = '<td><input type="text" class="room_types" onblur="edit_rooms_select();" /></td>';
rmtypescounter++;
}
function rooms(ID){
document.getElementById(ID).insertRow(roomscounter).innerHTML = '<td><input type="text" /></td><select class="room_type_select"><option value="Please Choose">Please Choose</option></select></td>';
roomscounter++;
};
function edit_rooms_select(){
var roomtypelist = $('.room_type_select');
roomtypelist.empty()
$('#room_types_table tr td input').each(function(){
var text = $(this).val();
roomtypelist.append('<option value='+text+'>'+text+'</option>');
});
}
</script>
I've removed the Jquery that was removing the duplicates, since it was definately not working how it needs to...
I'm aware that I may be going about this completely the wrong way, and if using td tags or inputs etc is completely wrong, I'm happy to change the whole form it necessary.
I'm sure this isn't the most effective way to do what I need, but this is how I managed to get it to work...
My HTML...
<div id="rm_types_info">
<table id="room_types_table">
<tr>
<td><input type="text" name="2" class="room_types" onblur="edit_rooms_select();" /></td>
</tr>
</table>
<button type="button" onclick="rmtypes('room_types_table');">Add Another Room Type</button>
</div>
<div id="rooms_info">
<table id="rooms_table">
<tr>
<th>Room Number</th>
<th>Room Type</th>
</tr>
<tr>
<td><input type="text" /></td>
<td>
<select class="room_type_select" id="room_type_select1" >
<option value="1">Please Choose</option>
</select>
</td>
</tr>
</table>
<button type="button" onclick="rooms('rooms_table');edit_rooms_select();">Add Another Room</button>
</div>
And the JQuery scripts relevant. In particular, it was the final function "edit_rooms_select()", and specifically the "Add new options to each select" that I was struggling with.
<script>
var rmtypescount=3;
var room_type_select_count=2;
function rmtypes(){
$('#room_types_table tr:last').after('<tr><td><input type="text" name='+rmtypescount+' class="room_types" onblur="edit_rooms_select();" /></td></tr>');
rmtypescount++;
};
function rooms(){
$('#rooms_table tr:last').after('<tr><td><input type="text" /></td><td><select id="room_type_select'+room_type_select_count+'" class="room_type_select"><option value="1">Please Choose</option></select></td></tr>');
room_type_select_count++
};
function edit_rooms_select(){
$('#room_types_table tr td input').each(function(){
var name = $(this).attr('name');
var value = $(this).val();
//Add New Options to each select
$('#rooms_table select').each(function(){
var last = $(this).children('option:last').val();
if (name > last) {
$(this).append('<option value="'+name+'">'+value+'</option>');
};
});
//Change any room types that have been edited
$('.room_type_select option').each(function(){
var match = $(this).val();
if(name == match){
$(this).text(value)
};
});
//Remove Blank Entries
if(value == ''){
$('.room_type_select option[value='+name+']').remove();
};
});
};
</script>
I think that the edit_rooms_select function is much more expensive than it needs to be. For what I require, this isn't going to be a problem, but I would be very interested to see how other people suggest the lists are edited, following my requirements..
- All user inputs from the room_types_table must be options in the select boxes in the rooms_table
- Any input changed in the room_types_table must have its relevant option in the select boxes changed to match
- Any input that is left blank (or later deleted) from the room_types_table must be removed from the select boxes
- Any select box that has a selection which is then removed from the room_types_table must be reset back to its original "Please Choose" option.
If anyone can suggest better ways to do this, or can tidy my code in any way, I'd like to see the code, and also have it explained, as I'm very inexperienced with Javascript/Jquery.

jQuery toggle - Changing from select input to text input

I'm very new to using jQuery and JavaScript but here goes. I am trying to create a toggle function for my website. There is an input to select the name of the event which displays as default as a dropdown list of all the events in the database - but I want there to be an option to change it to manual input and type the name of the event as what ever you want.
I can get this to work fine! However I can't get the link to change the input BACK to a select box to work.
See my code below:
/// jQuery Code ///
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript">
function toggleEventInput() {
$("#EventNameDropDown")
.replaceWith('<input type="text" size="35" name="boxEvent" class="FieldInput" />');
$("#EventNameChange")
.replaceWith(' (Drop Down Input)');
}
function toggleEventInputBack() {
$("#EventNameDropDown")
.replaceWith('TEST');
$("#EventNameChange")
.replaceWith(' (Manual Input)');
}
</script>
/// HTML Code ///
<table>
<tr>
<td class="label">Event:</td>
<td>
<span id="EventNameDropDown">
<select name="boxEvent" class="FieldInput" style="width:254px;" />
<?= $EventNameDropDownList ?>
</select>
</span>
<span id="EventNameChange">
(Manual Input)
</span>
</td>
</tr>
<tr>
<td class="label">Company:</td>
<td><input type="text" size="35" name="boxEvent" class="FieldInput" /></td>
</tr>
</table>
As said, when you click the original link to '(Manual Input)' it works fine and changes it to a text box. But then when you click the '(Drop Down Input)' link it does nothing.
Any help would be appreciated.
You need to use .html() instead of .replaceWith(). The former replaces the contents of the element. The latter replaces the element itself. By using .replaceWith() you are replacing the <span> that contains the <select> too.
Krishna is suggesting that rather than just replace the html for the <select>, you first store it in a variable so you can put it back later.
You could store it as data on an element, like this:
function toggleEventInput() {
// Store the html for the <select>.
$('#EventNameDropDown').data('selectHtml', $('#EventNameDropDown').html());
$("#EventNameDropDown").html('<input type="text" size="35" name="boxEvent" class="FieldInput" />');
$("#EventNameChange").html(' (Drop Down Input)');
}
function toggleEventInputBack() {
$("#EventNameDropDown").html($('#EventNameDropDown').data('selectHtml'));
$("#EventNameChange").html(' (Manual Input)');
// Clear the html for the <select>. We will get it again later if we need it.
$('#EventNameDropDown').data('selectHtml', '');
}
Its better to add the drop-down list inside a div/span and while clicking the toggle button, store the data inside the div/span to a variable and replace the content with the input box. on next toggle, replace the div/span with that data in the variable. a status variable 0/1 will help to toggle the data..

Categories