I have a this table of input fields which I can add rows dynamically with help of KnockoutJS
<table id="sTypeTable" class="table table-bordered" hidden="hidden">
<tr>
<th> Name </th>
<th> Value </th>
<th> <a class="btn btn-primary btn-sm" onclick="addReqField(0);"><i class="fa fa-plus"></i></a></th>
</tr>
<!-- ko foreach: {data: requestFields, as: 'reqField'} -->
<tr id="sRow">
<td>
<input id="sName" data-bind="value: reqField[0]" onblur="createJSON()"/>
</td>
<td>
<input id="sValue" data-bind="value: reqField[0]" onblur="createJSON()"/>
</td>
<td>
<a class="btn btn-warning btn-sm" data-bind="click: removeResField2" ><i class="glyphicon glyphicon-remove"></i></a>
</td>
</tr>
<!-- /ko -->
</table>
<div class="col-md-11 ">
<textarea style="font-size: larger; min-height: 200px" class="form-control" id="requestData" oninput="storeValueOfTextArea()"></textarea>
</div>
From this inputs I'm generating
following Json object on textarea (id="requestData")
[
{
"users": [
{
"name": "John",
"value": "12"
},
{
"name": "Sarah",
"value": "13"
},
{
"name": "Tom",
"value": "14"
}
]
}
]
It works well, but now I need populate these input fields from Json object,
When object entered to textarea.
I have tried following way
<script th:inline="javascript">
function storeValueOfTextArea() {
var lines = $('#requestData').val();
var texts = JSON.parse(lines);
for (var i=0; i!== texts[0].users.length;i++){
addReqField(); // method for adding new row of input fields
let v = texts[0].users[i];
$("tr[id=sRow]").each(function() {
$("#sName").val(v.name);
$("#sValue").val(v.value);
});
}
</script>
but in result only first input field gets the last object
{
"name": "Tom",
"value": "14"
}
others stays empty
$("tr[id=sRow]").each(function() {
$("#sName").val(v.name);
$("#sValue").val(v.value);
});
This doesn't seem to be good. You should get the row index you want, according to the index of the user for which data you want to fill. Right now what this does is to fill every row with the same user data, in all iterations of the for loop. In the end, the last user data will be in all rows.
I think the problem is that you're giving each created new row the same ID of sRow.
So inside your loop
$("tr[id=sRow]").each(function() {
$("#sName").val(v.name);
$("#sValue").val(v.value);
});
in the last iteration this will fill all sRow elements with the objects last values of Tom and 14.
Try giving your rows an unique id like sRow + a counter from 0 onwards sRow0 sRow1...
Thank you all who have answered to this question.
I have solved this problem by this way
for (let i=0; i!== texts[0].values.length;i++){
addReqField();
let v = texts[0].values[i];
$("tr[id=sRow]").each(function(index) {
if (index === i){
$(this).find("#sName").val(v.name);
$(this).find("#sValue").val(v.value);
}
});
}
Related
I have a table where data is populating. Each row has an edit link. I want to edit only a particular row on click of edit link. Right now its' showing edit option for all the rows.
Also I want to show the text in a input box on click of edit.
Here is my code.
<tr *ngFor="let row of backendData.report" class="hover-highlight">
<td class="benchmark_name">
{{row.name}}
</td>
<td>
{{row.value}}
</td>
<td>
{{row.description}}
</td>
<td>
<button *ngIf="enableEdit" (click)="enableEdit=false" class="btn page-secondary-action-btn" ng-click="cancel()">Cancel</button>
<button *ngIf="enableEdit" id="saveBtn" class="btn page-primary-action-btn" (click)="saveSegment()" type="submit">Save</button>
<a class="table-row-action edit-action" *ngIf="!enableEdit" (click)="enableEdit = true">
<i class="fa fa-pencil" uib-tooltip="Edit" tooltip-trigger="mouseenter" tooltip-append-to-body="true" tooltip-placement="left"></i>
</a>
</td>
<td>
</td>
</tr>
My current output looks like this
Here is the solution
html
<tr *ngFor="let row of backendData; index as i;" class="hover-highlight">
<td class="benchmark_name">
{{row.name}}
</td>
<td>
{{row.value}}
</td>
<td>
{{row.description}}
</td>
<td>
<button *ngIf="enableEdit && enableEditIndex == i" (click)="enableEdit=false" class="btn page-secondary-action-btn" ng-click="cancel()">Cancel</button>
<button *ngIf="enableEdit && enableEditIndex == i" id="saveBtn" class="btn page-primary-action-btn" (click)="saveSegment()" type="submit">Save</button>
<a href="#" class="table-row-action edit-action" *ngIf="!enableEdit" (click)="enableEditMethod($event, i)">
edit
</a>
</td>
<td>
</td>
</tr>
ts file
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
enableEdit = false;
enableEditIndex = null;
backendData = [{
"name": 'Target',
"value": '100',
"description": 'abc'
},
{
"name": 'Size',
"value": '20',
"description": 'def'
},
{
"name": 'Industry',
"value": '40',
"description": 'ghi'
}]
enableEditMethod(e, i) {
this.enableEdit = true;
this.enableEditIndex = i;
console.log(i, e);
}
}
Working Demo
Let me know if you have any doubt.
You have to create an index in loop
Then create an array of enableEdit of length i.
Then on click event, write a function which takes a parameter index i.
What you can do is set the "contenteditable" property of the row set to "true".
For example :
By default HTML keeps this to false.
You can get the current index of the table row using either by "trackBy" in *ngFor
*ngFor="let post of posts;trackBy:post?.id"
or you can use this keyword for the current index.
While saving or cancel just make the td's contenteditable to false.
I have a restaurant_form which allows user to input menu items. Each menu item represent a table row which is added dynamically. Each table row has input for: menu item, price, halal(Boolean), and notes.
Here is a sample entry. data-ids and names of input elements are incremented.
<tbody class="menu-entry ">
<tr id='menu0' data-id="0" class="hidden">
<td data-name="name" class="name">
<input type="text" name='name0' placeholder='Menu Item' class="form-control"/>
</td>
<td data-name="price">
<input type="text" name='price0' placeholder='0.00' class="form-control"/>
</td>
<td data-name="halal">
<input type="checkbox" name="veg0" value="halal" class="form-control">
</td>
<td data-name="notes">
<textarea name="notes0" placeholder="Contains soy." class="form-control"></textarea>
</td>
<td data-name="del">
<button name="del0" class='btn btn-danger glyphicon glyphicon-remove row-remove'></button>
</td>
</tr>
</tbody>
What is the best way to retrieve data from the table? I have tried this:
$('#restaurant_form').submit(function () {
$('.menu-entry').each(function()
{
$(this).find('td').each(function(){
$(this).find("input").each(function() {
alert(this.value)
});
$(this).find("textarea").each(function() {
alert(this.value)
});
})
})
})
The alert() shows the correct values however I am wondering if there is a better way to do this?
Edit I simplified it using:
$('.menu-entry .form-control').each()
Also, after retrieving the values, how can I pass it to the view with a POST request? I would like to save the values to model
RestaurantMenu with columns name, price, halal and notes.
Thank you.
Here's what I did:
For every menu entry, I converted the values to a string separated by comma and added a hidden input to hold the value. I added class 'menu-row' to tr.
$('#restaurant_form').submit(function () {
$('.menu-row').each(function(){
var menu_entry = ""
$(this).find('.form-control').each(function(){
menu_entry = menu_entry + this.value + ","
})
$('#restaurant_form').append('<input type="hidden" name="menu_entries" value="'+ menu_entry +'" />')
alert(menu_entry)
})
})
In views.py :
menu_entries = request.POST.getlist('menu_entries')
for menu_entry in menu_entries:
entry = menu_entry.split(",")
if entry[1]:
price = round(float(entry[1]), 2)
else:
price = 0.00
if not entry[2]:
entry[2] = False
MenuItems.objects.create(name=entry[0], price=price, halal=entry[2], notes=entry[3], restaurant_id=r.id)
If anyone knows a better approach, I would love to know. Thank you!
I'm using DataTable.js version 1.10.7 in my application. My intention is to get an Array of row data that was added to the table after initiation. I have followed a modified version of steps as in this documentation - https://datatables.net/reference/api/rows().data()
<!-- this form is filled and form values are added the datatable on submission-->
<div class="col-md-4">
<form action="../api/MaterialInPurchaseOrders/Create" id="create-material-in-purchaseOrder" method="POST">
<div id="name-group" class="form-group">
<label for="name">Material Name</label>
<select name="MaterialId" class="form-control" id="MaterialList"></select>
<br />
<label for="email">Quantity</label>
<input type="number" class="form-control" name="Quantity" placeholder="eg :- 100">
<label for="email">Quantity</label>
<input type="number" class="form-control" name="Cost" placeholder="eg :- 100">
</div>
<button type="submit" class="btn btn-default">Add Material to P/O<span class="fa fa-arrow-right"></span></button>
</form>
</div>
<!-- this table stores the rows that is being added from the form-->
<div class="col-md-8">
<table id="materials-in-purchase-order" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Material Id</th>
<th>Material Name</th>
<th>Quantity</th>
<th>Unit Cost</th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th>Material Id</th>
<th>Material Name</th>
<th>Quantity</th>
<th>Unit Cost</th>
</tr>
</tfoot>
</table>
</div>
<button class="btn btn-success" id="get-table-data">Get Table Row Data</button>
<script>
// the Datatable handler
var materialsInPurchaseOrder = $("#materials-in-purchase-order").DataTable({
"dataSrc": "data",
"columns": [
{ "data": "MaterialId" },
{ "data": "MaterialName" },
{ "data": "Quantity" },
{ "data": "Cost" }
]
});
$(document).ready(function () {
// loading list boxes from database to an input selection list box in the form
loadListBox("../api/Materials/GetMaterials", "#MaterialList", "MaterialId", "MaterialName");
// on submission of the form the form values gets updated to the Datatable as a row.
$("#create-material-in-purchaseOrder").on("submit", function (event) {
var data = {};
data = getFormValues("#create-material-in-purchaseOrder");
$("#MaterialList option:selected").each(function () {
data["MaterialName"] = $(this).html();
});;
materialsInPurchaseOrder.row.add(data).draw(false);
event.preventDefault();
});
$("#get-table-data").click(function (event) {
var materials = materialsInPurchaseOrder.rows().data();
console.log(materials);
// looping through each row of the array and doing something
for (var material in materials) {
// unable to do this because materials is not an array :(
}
event.preventDefault();
});
});
</script>
I get the below output for the console.log() instead of an Array
[Object, context: Array[1], selector: Object, ajax: Object]
Some research I did,
jQuery DataTables - Access all rows data
How can I get an Array of DataTable row data.?
As per the documentation return type of rows().data() is DataTables.Api. Before print it with console.log first convert it to string using JSON.stringify(). Because DataTables.Api is an object.
Ex:
console.log('Materials',JSON.stringify(materials));
As per the documentation of DataTables.Api type The API object is array-like
You can access data by row index as follows,
materials[0]
This returns data of first row.
The problem is solved with the help of the answer by #Dushan. This answer demonstrates how the actual code is changed.
I replaced this code
for (var material in materials) {
// unable to do this because materials is not an array :(
}
with this code
// looping through each row until the last row
for (var i=0 ; i < materials.length ; i++) {
console.log(materials[i]);
}
The only thing I'm adding to #Dushan's answer is the for loop which loops through Objects of the data objects in DataTables.Api to demonstrate the use of DataTables.Api Object.
Summarizing what #Dushan pointed out in the documentation, the return type of the rows().data() method is a DataTables.Api object not an Array. This is an array like object which is of length equal to the number of rows in the DataTable instance.
i recently developed a rest service that accept json data in this format
{
"foods": "food1, food2, food3",
"qty": "1,2,3"
}
but my javascript generate this format
["food1","1","food2","2","food3","3"]
i wrote my rest in php
data's are from this table body
<tbody id="tr">
<tr>
<td class="data">food1</td>
<td class="data">1</td>
<td>
<div class="col-sm-1">
<button type="button" class="btn btn-danger removethisfood">-</button>
</div>
</td>
</tr>
<tr>
<td class="data">food1</td>
<td class="data">1</td>
<td>
<div class="col-sm-1">
<button type="button" class="btn btn-danger removethisfood">-</button>
</div>
</td>
</tr>
<tr>
<td class="data">food1</td>
<td class="data">1</td>
<td>
<div class="col-sm-1">
<button type="button" class="btn btn-danger removethisfood">-</button>
</div>
</td>
</tr>
</tbody>
my java script code
var tbl = $('#tr').map(function() {
return $(this).find('td.data').map(function() {
return $(this).html();
}).get();
}).get();
console.log(JSON.stringify(tbl));
You can achieve the format required by looping over each tr and adding the text of the relevant td to an array, before building the final object by joining the text of the arrays together, something like this:
var foods = [], qty = [];
$('tr').each(function() {
var $row = $(this);
foods.push($row.find('td:eq(0)').text());
qty.push($row.find('td:eq(1)').text());
})
var obj = {
foods: foods.join(','),
qty: qty.join(',')
};
That said, your JSON format could be improved for clarity and simplicty of serialisation/deserialisation. It would make more sense to send an array with each item contained in an object with the parameters being its name and quantity, like this:
var obj = $('tr').map(function() {
var $row = $(this);
return {
food: $row.find('td:eq(0)').text(),
qty: $row.find('td:eq(1)').text()
}
}).get()
This output then looks like this:
[{
"food": "food1",
"qty": "1"
},{
"food": "food2",
"qty": "1"
},{
"food": "food3",
"qty": "1"
}]
Working example
I have two buttons: Activated and paused.
I want one of button to be disabled when I select the row of table.
IN HTML:
<div class="pull-right">
<button ng-disabled ="orders.status == pause" id = "activated" class="pull-left btn btn-primary">Activated</button>
<button ng-disabled ="orders.status == activated" id = "paused" class="pull-left btn btn-primary">Paused</button>
</div>
<br/>
<br/>
<table class="table table-color table-bordered table-hover">
<thead>
<tr>
<th>
Rotation Order
</th>
<th>
Tag Name
</th>
<th>
Status
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="orders in vm.rotationTable" ng-class="{selected : orders.rotationOrder == vm.idSelectedOrder}" ng-click="vm.setSelected(orders.rotationOrder)">
<td>{{orders.rotationOrder}}</td>
<td>{{orders.tagName}}</td>
<td>{{orders.status}}</td>
</tr>
</tbody>
</table>
In JScript:
// Code goes here
var myApp = angular.module('myApp',[]);
myApp.controller('tagController', ['$scope',function ($scope) {
var vm = this;
vm.rotationTable = [
{
"rotationOrder": "1",
"tagName": "Tag D",
"status":"Activated"
},
{
"rotationOrder": "2",
"tagName": "Tag E",
"status": "Paused"
},
{
"rotationOrder": "3",
"tagName": "Tag F",
"status": "Activated"
}
]
vm.idSelectedOrder = null;
vm.setSelected = function (index) {
vm.idSelectedOrder = index;
console.log(vm.idSelectedOrder);
};
}]);
you can see my work here.
http://plnkr.co/edit/UiMhLbzhxg3I5cGuiK0J?p=preview
and also If anyone can suggest:- How to fix hover of table row when its already selected?I do not want hover effect on row when it is already selected.
Change your ng-click to
ng-click="vm.setSelected(orders)"
And instead of storing vm.idSelectedOrder, store the actual order. Create a vm.selectedOrder variable for the controller.
And in your button you'll use:
ng-disabled ="vm.selectedOrder.status == 'Paused'"
This is the plunk.