Create a list of dict with VueJS - javascript

I have an HTML table where I took some values displayed in the table and other inputed by user and only for the row the checkbox is checked.
A row of my table looks like this:
Here is the code of my table:
<template>
<table id="Ref" class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Type</th>
<th scope="col">Nouvel ID</th>
<th scope="col">Nouveau Type</th>
<th scope="col">Nouvel URL</th>
<th scope="col">Nouvelle date d'expiration</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows">
<td> <a :href="row.url" target="_blank" rel="noreferrer noopener">{{ row.id }}</a></td>
<td> {{ row.typ }} </td>
<td> <input v-model.trim="row.newID" type="text" placeholder="ID"> </td>
<td> <input v-model.trim="row.newType" type="text" placeholder="Type"> </td>
<td> <input v-model.trim="row.newURL" type="text" placeholder="URL"> </td>
<td> <input v-model.trim="row.newExpDate" type="text" placeholder="Date d'expiration"> </td>
<td style="text-align: center; vertical-align: middle;"> <input v-model="row.isSelected" type="checkbox"> </td>
</tr>
</tbody>
</table>
</template>
My goal is to return a list of dict like this:
[{
"id1": "newID1",
"type1": "newType1",
"url1": "newURL1",
"exp1" "expDate1"
},
{
"id2": "newID2",
"type2": "newType2",
"url2": "newURL2",
"exp2" "expDate2"
},
{
"id3": "newID3",
"type3": "newType3",
"url3": "newURL3",
"exp3" "expDate3"
}]
I tried with reduce but it will only return me a dict, not a list.
putInvalidsRef() {
const selectedRef = this.rowsInvalidsRef.filter((ref) => ref.isSelected === true);
const refsDicts = selectedRef.reduce((acc, item) => {
acc[item.id] = item.newID || null;
acc[item.typ] = item.newType || null;
acc[item.url] = item.newURL || null;
acc[item.exp] = item.newExpDate || null;
return acc;
}, {});
console.log(refsDict);
this.$http.admin.putInvalidsRef(refsDict)
.then(getInvalidsRef);
}
Sorry if the answer is trivial, I'm really new to frontend.

Instead of {} use [] to return list:
function putInvalidsRef() {
const selectedRef = this.rowsInvalidsRef.filter((ref) => ref.isSelected === true);
const refsDicts = selectedRef.reduce((acc, item) => {
return [
...acc,
{
[item.id]: item.newID || null, // Be sure if here item has id and newID property
[item.typ]: item.newType || null,
[item.url]: item.newURL || null,
[item.exp]: item.newExpDate || null
}
]
}, []);
console.log(refsDicts);
this.$http.admin.putInvalidsRef(refsDicts)
.then(getInvalidsRef);
}

Related

Why is <input type='number' value={var_name}> replacing all the values in a table?

I am trying to map out a number of elements in a table and each of the elements has a specific value. Whenever i use value={inputArrival} or value={inputBurst} all the values of the specific column get update. I am attaching a screenshot. How to fix this?
Screenshot of what's happening
import React,{useState} from 'react';
import './tableEdit.css';
const EntryTable = (props) => {
const entry=props.numOfEntries;
const[inputArrival,SetinputArrival]=useState('');
const[inputBurst,SetinputBurst]=useState('');
function changeArrival(e)
{
console.log(e.target.value+"A");
/*
if(!Number(e.target.value))
return;
else*/
SetinputArrival(e.target.value);
}
function changeBurst(e)
{
console.log(e.target.value+"B");
SetinputBurst(e.target.value);
}
// console.log(entry);
var ArrayEntry=[];
for(var i=1;i<=entry;i++)
ArrayEntry.push( <tr key={i}>
<td className='row_editContent' >P{i}</td>
<td className='row_editContent'><input className='input_edit' placeholder='0' type='number' value={inputArrival} onChange={(e)=>changeArrival(e)}></input>ms</td>
<td className='row_editContent'><input className='input_edit' placeholder='0' type='number' value={inputBurst} onChange={(e)=>changeBurst(e)}></input>ms</td>
</tr>);
return (
<div>
<table className='MainTableContainer' >
<thead>
<tr >
<th className='row_editHeading'>Process</th>
<th className='row_editHeading'>Arrival Time</th>
<th className='row_editHeading'>Burst Time</th>
</tr>
</thead>
<tbody>
{ArrayEntry}
</tbody>
</table>
</div>
)
}
export default EntryTable
You are using the same single states inputArrival and inputBurst for every row entry of data in the table. Update so each is an array of strings, and update the changeArrival and changeBurst callbacks to curry an index to update. Use the mapped index to access the correct state and pass to the onChange callbacks.
const EntryTable = (props) => {
const entry = props.numOfEntries;
const [inputArrival, setInputArrival] = useState(Array(entry).fill(""));
const [inputBurst, setInputBurst] = useState(Array(entry).fill(""));
function changeArrival(index) {
return (e) => {
console.log(e.target.value + "A");
setInputArrival((values) =>
values.map((value, i) => (i === index ? e.target.value : value))
);
};
}
function changeBurst(index) {
return (e) => {
console.log(e.target.value + "B");
setInputBurst((values) =>
values.map((value, i) => (i === index ? e.target.value : value))
);
};
}
// console.log(entry);
const ArrayEntry = Array.from({ length: entry}).map((_, i) => (
<tr key={i}>
<td className="row_editContent">P{i}</td>
<td className="row_editContent">
<input
className="input_edit"
placeholder="0"
type="number"
value={inputArrival[i]}
onChange={changeArrival(i)}
/>
ms
</td>
<td className="row_editContent">
<input
className="input_edit"
placeholder="0"
type="number"
value={inputBurst[i]}
onChange={changeBurst(i)}
/>
ms
</td>
</tr>
));
return (
<div>
<table className="MainTableContainer">
<thead>
<tr>
<th className="row_editHeading">Process</th>
<th className="row_editHeading">Arrival Time</th>
<th className="row_editHeading">Burst Time</th>
</tr>
</thead>
<tbody>{ArrayEntry}</tbody>
</table>
</div>
);
};

How to return a list of value in all cells of a column with VueJS

I have an HTML table like this:
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nouveaux FDES</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows">
<td> {{ row.details.id_inies }} </td>
<td> <a :href="row.url" target="_blank" rel="noreferrer noopener">{{ row.name }}</a></td>
<td style="text-align: center; vertical-align: middle;"> <input v-model="row.isSelected" type="checkbox"> </td>
</tr>
</tbody>
My goal is to get value in cells of the column ID and only the ones which are selected by user using the checkbox
I try something like this but it doesn't work:
{
const selectedFDES = this.rowsScraped.filter((fdes) => fdes.isSelected === true);
const idList = selectedFDES.reduce((acc, item) => {
acc[item.details.id_inies] = [];
return acc;
}, []);
console.log(idList);
this.$http.admin.putScrapedFDES(idList);
}
Your reducer function doesn't make much sense. It should probably look like this:
const selectedFDES = this.rowsScraped.filter(r => r.isSelected);
const idList = selectedFDES.reduce((acc, item) => {
acc.push(item.details.id_inies);
return acc;
}, []);
console.log(idList);
this.$http.admin.putScrapedFDES(idList);
For your case, I believe a .map() would be shorter, cleaner and more readable:
const idList = this.rowsScraped
.filter(r => r.isSelected)
.map(r => r.details.id_inies);
this.$http.admin.putScrapedFDES(idList);
See it working here:
new Vue({
el: '#app',
data: () => ({
rows: ['First', 'Second', 'Third']
.map((name, i) => ({
name: `${name} row`,
details: {
id_inies: i + 1,
},
url: '#',
isSelected: false
}))
}),
computed: {
selectedRows() {
return this.rows
.filter(row => row.isSelected)
.map(row => row.details.id_inies)
}
},
watch: {
selectedRows(newVal, oldVal) {
// This runs every time selectedRows changes value
console.log({ newVal, oldVal });
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2"></script>
<div id="app">
<table>
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nouveaux FDES</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows">
<td> {{ row.details.id_inies }} </td>
<td> <a :href="row.url" target="_blank" rel="noreferrer noopener">{{ row.name }}</a></td>
<td style="text-align: center; vertical-align: middle;"> <input v-model="row.isSelected" type="checkbox"> </td>
</tr>
</tbody>
</table>
<pre v-text="selectedRows" />
</div>

Component template should contain exactly one root element nuxt

I'm not sure what could be the issue here but I'm using nuxt to make a SPA app. and I'm getting an error from an already compiled piece of code I got from codepen. link to codepen
https://codepen.io/jjelic/pen/yevNLZ?editors=1010
When I try this code my my nuxt app I get an error.
I've added a file called monitor.vue in pages folder and added the html and js like so
Is this root element error common as I have never encountered it before with html and how can I avoid?
Vue.filter('currencyDisplay', {
// model -> view
read: function(val) {
if (val > 0) {
return accounting.formatMoney(val, "$", 2, ".", ",");
}
},
// view -> model
write: function(val, oldVal) {
return accounting.unformat(val, ",");
}
});
Vue.directive('sortable', {
twoWay: true,
deep: true,
bind: function() {
var that = this;
var options = {
draggable: Object.keys(this.modifiers)[0]
};
this.sortable = Sortable.create(this.el, options);
console.log('sortable bound!')
this.sortable.option("onUpdate", function(e) {
that.value.splice(e.newIndex, 0, that.value.splice(e.oldIndex, 1)[0]);
});
this.onUpdate = function(value) {
that.value = value;
}
},
update: function(value) {
this.onUpdate(value);
}
});
var vm = new Vue({
el: '#app',
data: {
rows: [
//initial data
{
qty: 5,
description: "Something",
price: 55.20,
tax: 10
},
{
qty: 2,
description: "Something else",
price: 1255.20,
tax: 20
},
],
total: 0,
grandtotal: 0,
taxtotal: 0,
delivery: 40
},
computed: {
total: function() {
var t = 0;
$.each(this.rows, function(i, e) {
t += accounting.unformat(e.total, ",");
});
return t;
},
taxtotal: function() {
var tt = 0;
$.each(this.rows, function(i, e) {
tt += accounting.unformat(e.tax_amount, ",");
});
return tt;
}
},
methods: {
addRow: function(index) {
try {
this.rows.splice(index + 1, 0, {});
} catch (e) {
console.log(e);
}
},
removeRow: function(index) {
this.rows.splice(index, 1);
},
getData: function() {
$.ajax({
context: this,
type: "POST",
data: {
rows: this.rows,
total: this.total,
delivery: this.delivery,
taxtotal: this.taxtotal,
grandtotal: this.grandtotal,
},
url: "/api/data"
});
}
}
});
<template>
<div class="panel-body" id="app">
<table class="table table-hover">
<thead>
<tr>
<th style="width: 20px;">No.</th>
<th>Description</th>
<th style="width: 80px;">Qty</th>
<th style="width: 130px;" class="text-right">Price</th>
<th style="width: 90px;">Tax</th>
<th style="width: 130px;">Total</th>
<th style="width: 130px;"></th>
</tr>
</thead>
<tbody v-sortable.tr="rows">
<tr v-for="row in rows" track-by="$index">
<td>
{{ $index +1 }}
</td>
<td>
<input class="form-control" v-model="row.description" />
</td>
<td>
<input class="form-control" v-model="row.qty" number />
</td>
<td>
<input class="form-control text-right" v-model="row.price | currencyDisplay" number data-type="currency" />
</td>
<td>
<select class="form-control" v-model="row.tax">
<option value="0">0%</option>
<option value="10">10%</option>
<option value="20">20%</option>
</select>
</td>
<td>
<input class="form-control text-right" :value="row.qty * row.price | currencyDisplay" v-model="row.total | currencyDisplay"
number readonly />
<input type="hidden" :value="row.qty * row.price * row.tax / 100" v-model="row.tax_amount | currencyDisplay"
number />
</td>
<td>
<button class="btn btn-primary btn-xs" #click="addRow($index)">add row</button>
<button class="btn btn-danger btn-xs" #click="removeRow($index)">remove row</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-right">TAX</td>
<td colspan="1" class="text-right">{{ taxtotal | currencyDisplay }}</td>
<td></td>
</tr>
<tr>
<td colspan="5" class="text-right">TOTAL</td>
<td colspan="1" class="text-right">{{ total | currencyDisplay }}</td>
<td></td>
</tr>
<tr>
<td colspan="5" class="text-right">DELIVERY</td>
<td colspan="1" class="text-right"><input class="form-control text-right" v-model="delivery | currencyDisplay"
number /></td>
<td></td>
</tr>
<tr>
<td colspan="5" class="text-right"><strong>GRANDTOTAL</strong></td>
<td colspan="1" class="text-right"><strong>{{ grandtotal = total + delivery | currencyDisplay }}</strong></td>
<td></td>
</tr>
</tfoot>
</table>
<button #click="getData()">SUBMIT DATA</button>
<pre>{{ $data | json }}</pre>
</div>
</template>
This problem is actually a very simple problem. I don't know vue, but the render method has the same limits of react's one: every component must have only one root element in its template.
This means that a situation like this isn't accepted:
<template>
<div></div>
<div></div>
</template>
But like this is correct:
<template>
<div></div>
</template>
This means that surely, somehow in the code you didn't show us, you're putting two elements as root of your template

How to filter JS table using multiple inputs

I am writing c# application . I have to filter Js table using multiple inputs. When i type something into only one input it works fine, but if I want to search table for example by "Service Price" and "Parts Price" it finds nothing.
<form id="search-repairs">
<p>
Service Price : <input type="text" id="searchServicePrice" class="searchInput" onkeyup="searchingEngine(3)" />
Parts Price : <input type="text" id="searchPartsPrice" class="searchInput" onkeyup="searchingEngine(2)" />
Summary Price : <input type="text" id="searchBySumPrice" class="searchInput" onkeyup="searchingEngine(5)" />
Date : <input type="text" id="searchDate" class="searchInput" onkeyup="searchingEngine(0)" />
</p>
</form>
<table id="table" class="table table-striped table-hover">
<thead>
<tr>
<th>
Date
</th>
<th>
Description
</th>
<th>
PartsPrice
</th>
<th>
Price
</th>
<th>
ServicerId
</th>
<th>
summaryPrice
</th>
</tr>
</thead>
<tbody id="searchBody">
#foreach (var item in Model)
{
var price = item.Price;
var partsPrice = item.PartsPrice;
var sum = price + partsPrice;
<tr>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.PartsPrice)
</td>
<td name="price">
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.ServicerId)
</td>
<td>
#Html.DisplayFor(modelItem => sum);
</td>
</tr>
}
</tbody>
</table>
And here is my code to filter this table. It is plain javascript code. I think there is something wrong in filter variable. I have tried a lot of different solutions but it didn't want to work in any case.
function searchingEngine(col) {
var table, trs, searchByPrice, searchByPartsPrice, searchByDate, searchBySumPrice, filter, i, td;
table = document.getElementById("table");
trs = table.getElementsByTagName("tr");
searchByPrice = document.forms['search-repairs'].querySelector("#searchServicePrice");
searchByPartsPrice = document.forms['search-repairs'].querySelector("#searchPartsPrice");
searchByDate = document.forms['search-repairs'].querySelector("#searchDate");
searchBySumPrice = document.forms['search-repairs'].querySelector("#searchBySumPrice");
filter = searchByPrice.value.toUpperCase() || searchByPartsPrice.value.toUpperCase() ||
searchByDate.value.toUpperCase() || searchBySumPrice.value.toUpperCase();
for (i = 0; i < trs.length; i++) {
td = trs[i].getElementsByTagName("td")[col];
if (td) {
if (td.textContent.toUpperCase().indexOf(filter) > -1) {
trs[i].style.display = "";
} else {
trs[i].style.display = "none";
}
}
}
}

Implement check all checkbox in react && angular

I'm trying to implement check all feature on my checkbox element but I can't manage to do that.Can someone help ?
var FormattedDate = ReactIntl.FormattedDate;
var DiaryTable = React.createClass({
getInitialState: function() {
return {
items : this.props.item,
globalChecked: false
};
},
changeSelection:function (i) {
var state = this.state.items.map(function (element) {
return {
start:element.start,
end:element.end,
hours:element.hours,
selected:(element === this.state.items[i] ? !element.selected:element.selected)
};
});
},
render: function(){
var arrayItems = this.state.items.map(function (item,i) {
return (
<tr key={i}>
<td><input type="checkbox" checked={item.selected} onChange={this.changeSelection(i).bind(this)}/></td>
<td><FormattedDate value={item.start}/></td>
<td><FormattedDate value={item.end}/></td>
<td>{item.hours}</td>
<td>
<button className="editButton"></button>
</td>
<td>
{this.state.items[i].selected}
</td>
</tr>
);
}.bind(this));
return (
<table className="myTable">
<thead>
<tr>
<th><input type="checkbox"/></th>
<th>Start Date:</th>
<th>End Date:</th>
<th id="hoursField">Hours:</th>
<th id="editField">Edit:</th>
<th>selected:</th>
</tr>
</thead>
<tbody>
{arrayItems}
</tbody>
<tfoot>
<tr>
<td colSpan="4">
<button className="myButton" id="addPeriodButton">Add period</button>
<button className="myButton">Remove period</button>
<button className="myButton">Set result from merge</button>
</td>
</tr>
</tfoot>
</table>
);
}
});
I', taking data from my controller:
app.controller('MainCtrl', function ($scope) {
$scope.resultProps = {
item:[]
}
$scope.firstArrayProps = {
item:[{start:new Date(),end:22,hours:3,selected:false},{start:22,end:33,hours:44,selected:false}]
}
$scope.secondArrayProps = {
item:[{start:22,end:33,hours:44,selected:false}]
}
..... more code here
and index.html..
<body ng-app="app" ng-controller="MainCtrl as mainCtrl">
<!--<div id="diaryWrapper">-->
<!--<!–<diary-template props="firstArrayProps" result="resultProps" ></diary-template>–>-->
<!--<!–<div class="mergeWrapper">–>-->
<!--<!–<button class="myButton" id="mergeButton" ng-click="runMerge()">Merge diaries</button>–>-->
<!--<!–</div>–>-->
<!--<!–<diary-template props="secondArrayProps" result="resultProps" ></diary-template>–>-->
<!--</div>-->
<div class="tableWrapper">
<react-component name="DiaryTable" props="firstArrayProps" />
</div>
<div class="tableWrapper">
<react-component name="DiaryTable" props="secondArrayProps" />
</div>
If I'm doing wrong something else please feel free to tell me . Thank you !
The code for handleSelectAll should be:
handleSelectAll: function(e) {
var items = this.state.items.slice();
items.forEach(function(item) {
item.selected: e.target.checked,
});
this.setState({ items: items });
}

Categories