Change JSON Format in javascript - javascript

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

Related

jQuery Map To Retrieve Comma Separated Values Separately

I am using multiple text box to insert data into database table. So doing few researches and used online resources to make it work. But stuck into one basic thing, I guess. The issue is with the jQuery mapping. Let me share the code here:
//Add row to the table
$('#btnAddRow').on('click', function() {
var $clone = $('#tblQuesAns tbody tr:last').clone();
$clone.find('input').val('')
$('#tblQuesAns tbody').append($clone);
});
//Add more rows for option
$('body').on('click', '.addOptions', function() {
$(this).parent().append('<div><input class="txtOptions" type="text" /></div>');
});
//Get text box values
$('#btnGetValues').on('click', function() {
const allData = $('#tblQuesAns tbody tr').map(function() {
const $row = $(this),
question = $row.find('.txtQuestion').val(),
options = $row.find('.txtOptions').map(function() {
return this.value;
}).get().join(" ");
//return { question, options };
alert(question + ' ' + options.replace(/\s+/g, "_"));
}).get();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<button id="btnAddRow" type="button">
Add Row
</button>
<button id="btnGetValues" type="button">
Get Values
</button>
<table id="tblQuesAns" border="1">
<thead>
<tr>
<th>Question</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input class="txtQuestion" value="Capital of Englnad" />
</td>
<td>
<input class="txtOptions" value="London" />
<span class="addOptions">(+)</span>
</td>
</tr>
<tr>
<td>
<input class="txtQuestion" value="Current Pandemic" />
</td>
<td>
<input class="txtOptions" value="Corona" />
<span class="addOptions">(+)</span>
</td>
</tr>
</tbody>
</table>
By default, jQuery map uses comma and I tried to remove those by using replace method as follows:
options.join(' ').replace(/\s+/g, "_")
Now I may have options that may contain comma. For example:
Question Options
Question 1 New York
Jakarta
London, Paris
Munich
So problem is, the values having space from text boxes also get replaced with the underscore sign replace(/\s+/g, "_"). So I get this output:
New_York_Jakarta_London,_Paris_Munich
But my expected output is this:
New York_Jakarta_London, Paris_Munich
I tried a different way that works but in this case all the text box values get concatenated:
var options = $("input[name*='txtOptions']");
var str = "";
$.each(options, function(i, item) {
str += $(item).val();
});
The problem with the above is, when I've different questions say question 1, question 2, it'll merge all the options to both of them. Though I want specific options for both questions.
Something like this?
//Add row to the table
$('#btnAddRow').on('click', function() {
var $clone = $('#tblQuesAns tbody tr:last').clone();
$clone.find('input').val('')
$('#tblQuesAns tbody').append($clone);
});
//Add more rows for option
$('body').on('click', '.addOptions', function() {
$(this).parent().append('<div><input class="txtOptions" type="text" /></div>');
});
//Get text box values
$('#btnGetValues').on('click', function() {
const allData = $('#tblQuesAns tbody tr').map(function() {
const $row = $(this),
question = $row.find('.txtQuestion').val(),
options = $row.find('.txtOptions').map(function() {
return this.value;
}).get().join("_");
return {question,options}
}).get()
const x = allData.map(item => `${item.question}_${item.options}`).join(" ")
console.log(x)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<button id="btnAddRow" type="button">
Add Row
</button>
<button id="btnGetValues" type="button">
Get Values
</button>
<table id="tblQuesAns" border="1">
<thead>
<tr>
<th>Question</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input class="txtQuestion" value="Capital of England" />
</td>
<td>
<input class="txtOptions" value="London" />
<span class="addOptions">(+)</span>
</td>
</tr>
<tr>
<td>
<input class="txtQuestion" value="Current Pandemic" />
</td>
<td>
<input class="txtOptions" value="Corona" />
<span class="addOptions">(+)</span>
</td>
</tr>
</tbody>
</table>

How to populate dynamically added input fields with Json object

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);
}
});
}

save dynamic table into json

what is the best way to save a dynamic table data in to json.
I have two tables that i want to save in to one json file.
i"m able to console the regular table data but i"m unable to locate the td value of a dynamic table.
my plan to save to json and clear the forum for additional DC/pop info adding
so please check the save button and help me understand how to continue
1. save the popisp table
2. clear and make it ready for the next pop entry.
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js">
$(document).ready(function(){
$(".add-row").click(function(){
var name = $("#ispname").val();
var capasity = $("#ispcapasity").val();
var markup = "<tr><td><input type='checkbox' name='record'></td><td>" + name + "</td><td>" + capasity + "</td></tr>";
$('#popisp tr:last').after(markup);
});
$(".delete-row").click(function(){
$('#popisp').find('input[name="record"]').each(function(){
if($(this).is(":checked")){
$(this).parents("tr").remove();
}
});
});
$(".save_asJSON").click(function(){
var pop_name = document.getElementById("popname").value
jsonobj.pops[pop_name] = {
name: document.getElementById("popname").value,
city: document.getElementById("popcity").value,
subnet: document.getElementById("popsubnet").value,
}
console.log(jsonobj);
});
});
var jsonobj = {
pops: {}
};
</script>
<body>
<table id="PoP_Details">
<tr>
<td>Pop name:</td>
<th colspan="2"><input id="popname" name='pops[name]'></input></th>
</tr>
<tr>
<td>City:</td>
<th colspan="2"><input id="popcity" name='pops[name][city]'></input></th>
<tr>
<td>POP Subnet</td>
<th colspan="2"><input id="popsubnet" name='pops[name][subnet]'></input></th>
</tr>
</table>
<form>
<input type="text" id="ispname" placeholder="Name">
<input type="text" id="ispcapasity" placeholder="capasity">
<input type="button" class="add-row" value="Add ISP">
</form>
<div class="wrap">
<table id="popisp">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>capasity</th>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
</div>
<button type="button" class="delete-row">Delete Row</button>
<button type="button" class="save_asJSON">Save</button>
</body>
here is how I like my json to looks like
{
"pops": {
"pop1": {
"name": "pop1",
"city": "blabla",
"subnet": "192.168.1.0/24",
"isps": [
{
"name": "isp1",
"capasity": "10M"
},
{
"name": "isp2",
"capasity": "10M"
}
]
},
"pop2": {
"name": "pop2",
"city": "blabla",
"subnet": "192.168.2.0/24",
"isps": [
{
"name": "isp3",
"capasity": "20M"
},
{
"name": "isp4",
"capasity": "30M"
},
{
"name": "isp5",
"capasity": 500M"
}
]
}
}
}
I can suggest the following guidance :
Save inputs as jQuery variables for further use, not necessary but usefull, ex :
var $input = $('#popname');
Add a function that use the table, iterate through the <tr> in <tbody> and retrieve the <td> to compose object to save for each row, return it as an array.
Add a function that use the inputs to clear the form
Call the two function above when saving the array, the first to add the data to the json saved, the second to clear the form.
I show bellow an update of your snippet with complete modification, but I suggest you use use the guidance to implement it in a way that suits your needs.
$(document).ready(function(){
// Inputs as jQuery variables
var $nameInput = $("#popname");
var $cityInput = $("#popcity");
var $subnetInput = $("#popsubnet");
var $ispNameInput = $("#ispname");
var $ispCapacityInput = $("#ispcapasity");
var $popispTable = $('#popisp');
// array for convenience loop
var inputs = [$nameInput, $cityInput, $subnetInput,
$ispNameInput, $ispCapacityInput];
// function to clear all inputs and remove isp rows
function clearForm() {
inputs.forEach(e => e.val(''));
$popispTable.find('tbody').find('tr').remove();
$popispTable.find('tbody').append($('<tr>'));
}
// function that return an array of isp rows data
function ispTableData() {
var rows = $popispTable.find('tbody').find('tr');
if (!rows.length) return [];
console.log(rows.length);
var data = rows.toArray().reduce((data, e, k) => {
var tds = $(e).find('td');
if (!tds.length) return [];
data.push({
checked: $(tds[0]).find('input').is(":checked"),
name: $(tds[1]).text(),
capasity: $(tds[2]).text()
});
return data;
}, []);
return data;
}
$(".add-row").click(function(){
var name = $("#ispname").val();
var capasity = $("#ispcapasity").val();
var markup = "<tr><td><input type='checkbox' name='record'></td><td>" + name + "</td><td>" + capasity + "</td></tr>";
$('#popisp tr:last').after(markup);
// eventually clear row form inputs here as well
});
$(".delete-row").click(function(){
$('#popisp').find('input[name="record"]').each(function(){
if($(this).is(":checked")){
$(this).parents("tr").remove();
}
});
});
$(".save_asJSON").click(function(){
var pop_name = document.getElementById("popname").value
jsonobj.pops[pop_name] = {
name: $("#popname").val(),
city: $("#popname").val(),
subnet: $("#popsubnet").val(),
// add the isp rows data
isps: ispTableData()
}
console.log(jsonobj);
// clear the form
clearForm();
});
});
var jsonobj = {
pops: {}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<table id="PoP_Details">
<tr>
<td>Pop name:</td>
<th colspan="2"><input id="popname" name='pops[name]'></input></th>
</tr>
<tr>
<td>City:</td>
<th colspan="2"><input id="popcity" name='pops[name][city]'></input></th>
<tr>
<td>POP Subnet</td>
<th colspan="2"><input id="popsubnet" name='pops[name][subnet]'></input></th>
</tr>
</table>
<form>
<input type="text" id="ispname" placeholder="Name">
<input type="text" id="ispcapasity" placeholder="capasity">
<input type="button" class="add-row" value="Add ISP">
</form>
<div class="wrap">
<table id="popisp">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>capasity</th>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
</div>
<button type="button" class="delete-row">Delete Row</button>
<button type="button" class="save_asJSON">Save</button>
</body>

Can't print the Array in view using ng-repeat in angular JS

I have designed the dynamic table with the various type of the input field.We can add and delete the row as per the requirement.
Here is my HTML view code:
<body>
<div ng-app="appTable">
<div ng-controller="Allocation">
<button ng-click="add()"> Add </button>
<button ng-click="remove()">remove</button>
<table>
<th>
<td>Date</td>
<td>Project</td>
<td>Release</td>
<td>Feature</td>
<td>Module name</td>
<td>Hours spent</td>
<td>Comment</td>
</th>
<tr ng-repeat="data in dataList">
<td><input type="checkbox" ng-model="data.isDelete"/></td>
<td>
<input type="text"
datepicker
ng-model="data.date" />
</td>
<td><input type="text" ng-model="data.dept"/></td>
<td>
<select ng-model="data.release" ng-options="x for x in range">
</select>
</td>
<td>
<select ng-model="data.feature" ng-options="x for x in feature">
</select>
</td>
<td>
<input type = "text" ng-model = "data.modulename">
</td>
<td>
<select ng-model="data.hours" ng-options="x for x in hours">
</select>
</td>
<td>
<input type = "text" ng-model = "data.comment">
</td>
</tr>
</table>
<button ng-click="Submit()">Submit</button>
<tr ng-repeat="data in dataList">
<p>{{data.date}}</p>
<p>{{test}}</p>
</tr>
</div>
</div>
</body>
Here my angularJS script:
<script>
var app = angular.module("appTable", []);
app.controller("Allocation", function($scope) {
$scope.hours = ["1", "2", "3"];
$scope.range = ["1", "2", "3"];
$scope.feature = ["UT", "FSDS", "Coding/Devlopment", "QA"];
$scope.dataList = [{
date: '17/07/2016',
dept: 'OneCell',
release: '1',
feature: "UT",
modulename: "Redundancy",
hours: "1",
comment: "Add extra information"
}];
$scope.add = function() {
var data = {};
var size = $scope.dataList.length - 1;
data.date = $scope.dataList[size].date;
data.dept = $scope.dataList[size].dept;
data.release = $scope.dataList[size].release;
data.feature = $scope.dataList[size].feature;
data.modulename = $scope.dataList[size].modulename;
data.hours = $scope.dataList[size].hours;
data.comment = $scope.dataList[size].comment;
$scope.dataList.push(data);
};
$scope.Submit = function() {
$scope.test = "Submit is pressed...";
};
$scope.remove = function() {
var newDataList = [];
angular.forEach($scope.dataList, function(v) {
if (!v.isDelete) {
newDataList.push(v);
}
});
$scope.dataList = newDataList;
};
});
app.directive("datepicker", function () {
function link(scope, element, attrs, controller) {
// CALL THE "datepicker()" METHOD USING THE "element" OBJECT.
element.datepicker({
onSelect: function (dt) {
scope.$apply(function () {
// UPDATE THE VIEW VALUE WITH THE SELECTED DATE.
controller.$setViewValue(dt);
});
},
dateFormat: "dd/mm/yy" // SET THE FORMAT.
});
}
return {
require: 'ngModel',
link: link
};
});
</script>
I have taken the dataList array(list) to store the rows the of table.Every time when row will be added or deleted then respective element in the dataList array will be added and delete.
I have put the "submit" button in my view.When this button will be pressed then all the dataList element will be printed as shown here,
<button ng-click="Submit()">Submit</button>
<tr ng-repeat="data in dataList">
<p>{{data.date}}</p>
<p>{{test}}</p>
</tr>
But some how the dataList elements are not printed.However I am able to print the value of the test string.Please help.
Here you are using plain <tr> element for ng-repeat, this will not work, as it require proper structure of table.
E.g.:
<table>
<tr ng-repeat="data in dataList">
<td>
<p>{{data.date}}</p>
</td>
</tr>
</table>
P.S. : Your submit button is doing nothing. Just printing one statement. Above code of ng-repeat will work on each add and delete statement. i.e. it will print data simultaneously.

Passing calculated value to ng-model

I am new to AngularJS and am trying to set up a simple Orders form. I'm having problems passing the id value to the controller. I want it to be the last order id + 1 so it acts as an identity field. Ideally I'd like it to be hidden, but if I could just get this part working that would help.
Here is what I have tried:
HTML:
<div ng-controller = "OrdersCtrl">
<h1>Orders</h1>
<form class="form-inline" ng-submit="addOrder()">
<strong>Add order: </strong>
<input value="{{orders[orders.length - 1].id + 1 }}" ng-model="newOrder.id" >
<input type="number" step="0.01" class="form-control" placeholder="Total" ng-model="newOrder.total">
<input type="number" class="form-control" ng-model="newOrder.product_id">
<input type="submit" value="+" class="btn btn-success">
</form>
<table class="table table-hover">
<thead>
<td>Order ID</td>
<td>Total</td>
<td>Product</td>
<td></td>
</thead>
<tr ng-repeat="order in orders | orderBy: '-id':reverse">
<td>
{{order.id}}
</td>
<td>
<strong>{{order.total | currency}}</strong>
</td>
<td>
{{order.product_id}}
<small ng-show="order.user_id"><br>-{{order.user_id}}</small>
</td>
<td>
<button ng-click="deleteOrder(order)" class="btn btn-danger btn-sm"><span class="gylphicon glyphicon-trash" aria-hidden="true"></span></button>
</td>
</tr>
</table>
</div>
JS:
var app = angular.module('shop', []);
$(document).on('ready page:load', function() {
angular.bootstrap(document.body, ['shop'])
});
app.controller('OrdersCtrl', ['$scope', function($scope){
$scope.orders = [
{id: 1, total: 55, product_id: 5, user_id: 1},
{id: 2, total: 33, product_id: 3, user_id: 1},
{id: 3, total: 51, product_id: 12, user_id: 1}
];
$scope.addOrder = function(){
if(!$scope.newOrder.product_id || $scope.newOrder.total === ''){return;}
$scope.orders.push($scope.newOrder);
};
$scope.delOrder = function(order){
$scope.orders.splice($scope.orders.indexOf(order), 1);
};
}]);
I'm not getting any errors but nothing is appearing in the id column. Any advice would be appreciated.
Since $scope keeps all the existing orders, you shouldn't need to pass in a new id. Just calculate it in the controller when adding a new order.
remove this line from the view
<input value="{{orders[orders.length - 1].id + 1 }}" ng-model="newOrder.id" >
In controller
$scope.newOrder = {};
$scope.addOrder = function(){
if($scope.newOrder.total === ''){ return; }
$scope.newOrder.id = $scope.orders[$scope.orders.length - 1].id + 1
$scope.orders.push($scope.newOrder);
$scope.newOrder = {};
};

Categories

Resources