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 });
}
Related
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);
}
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>
I have this code in my render function, but I have 5 different versions with minor html changes. I made new tables with each of the 5. How would I optimize it so I do not have to repeat a lot of html/js code?
<table>
<thead>
<tr>
<th></th>
<th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody> { this.showData
this.state.data.map((exp) => {
if (exp.typeOfItem === "Asset" && exp.term == "Short-Term" ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'>
<Update expense={exp} />
</td>
<td className='button-col'>
<Delete expense={exp} />
</td>
</tr>
}
})
}
</tbody>
</table>
<table>
<thead>
<tr>
<th></th>
<th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
this.state.data.map((exp) => {
if (exp.typeOfItem === "Asset" && exp.term == "Long-Term" ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'>
<Update expense={exp} />
</td>
<td className='button-col'>
<Delete expense={exp} />
</td>
</tr>
}
})
}
</tbody>
</table>
You can pull out your Table in a custom component and pass down the data as props,
Your new component would be,
import React from 'react'
const TableComponent = (props) => (
<table>
<thead>
<tr>
<th></th><th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
props.data.map((exp) => {
if (exp.typeOfItem === props.typeOfItem && exp.term === props.term ) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{exp.description}</td>
<td className='button-col'>${exp.amount}</td>
<td className='button-col'> <Update expense={exp}/></td>
<td className='button-col'><Delete expense={exp} /></td>
</tr>
}
})
}
</tbody>
</table>
)
export default TableComponent
Now you can render this component by passing props,
<TableComponent data={this.state.data} typeOfItem="Asset" term="Short-Term"/>
<TableComponent data={this.state.data} typeOfItem="Asset" term="Long-Term"/>
Note: If you have any other variable's to be used in Table, do pass them as props and in your TableComponent use them appropriately.
You would be better off splitting the array before the render.
for instance:
const assets = this.state.data.filter(item => item.typeOfItem === "Asset");
const longTerm = [];
const shortTerm = [];
assets.forEach((asset) => {
asset.term = "long" ? longTerm.push(asset) : shortTerm.push(asset);
});
Next you can render it with a component you want
longTerm.map(asset => {
return <MyComponent amount={asset.amount} ... />
})
shortTerm.map(asset => {
return <MyComponent amount={asset.amount} ... />
})
And your component could be
function MyComponent(props) {
return <tr>
<td className='counterCell'></td>
<td className='desc-col'>{props.description}</td>
//rest
</tr>
}
additionally you could make a table component and pass it the collection which calls MyComponent
function TableComponent({collection}) {
return <table>
<thead>
<tr>
<th></th><th className='desc-col'>Description</th>
<th className='button-col'>Amount</th>
</tr>
</thead>
<tbody>
{
collection.map(asset => {
return <MyComponent ....
});
}
</tbody>
</table>
}
and then the initial render would just be
<>
<TableComponent collection={longterm} />
<TableComponent collection={shortterm} />
</>
I'm fairly new to Knockout and JavaScript in general, I am trying to figure out how to get this working I am trying to create a simple shopping list application using knockout.js I have it currently where it's adding the Item Name and quantity to the table however it's adding them both as separate rows instead of row and column.
HTML Table issue
var SimpleListModel = function(items) {
self = this;
self.items = ko.observableArray(items);
self.itemToAdd = ko.observable("");
self.quantityToAdd = ko.observable("");
self.deleteItem = function(item) {
self.items.remove(item);
return self.items;
}
self.addItem = function() {
if (self.itemToAdd() != "") {
self.items.push(self.itemToAdd());
self.itemToAdd("");
}
if (self.quantityToAdd() != "") {
self.items.push(self.quantityToAdd());
self.quantityToAdd("");
}
}.bind(this);
};
ko.applyBindings(new SimpleListModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<form data-bind="submit: addItem">
New item:<input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' /> Quantity:
<input data-bind='value: quantityToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button>
</form>
<p></p>
<table border="1">
<thead>
<th>Item</th>
<th>Quantity</th>
<th>Remove</th>
</thead>
<tbody data-bind="foreach:items">
<tr>
<td data-bind="text: $data"></td>
<td><input type="button" data-bind="click:$root.deleteItem" value="X"></input>
</td>
</tr>
</tbody>
</table>
the expected result needs to be:
Expected result image
That's because you're adding the item and the quantity to the items array as separate items. You'll want to use an object instead:
var SimpleListModel = function(items) {
self = this;
self.items = ko.observableArray(items);
self.itemToAdd = ko.observable("");
self.quantityToAdd = ko.observable("");
self.deleteItem = function(item) {
self.items.remove(item);
return self.items;
}
self.addItem = function() {
if (self.itemToAdd() && self.quantityToAdd()) {
self.items.push({ item: self.itemToAdd(), quantity: self.quantityToAdd() });
self.itemToAdd("");
self.quantityToAdd("");
}
};
};
ko.applyBindings(new SimpleListModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<form data-bind="submit: addItem">
New item:<input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' /> Quantity:
<input data-bind='value: quantityToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button>
</form>
<p></p>
<table border="1">
<thead>
<th>Item</th>
<th>Quantity</th>
<th>Remove</th>
</thead>
<tbody data-bind="foreach:items">
<tr>
<td data-bind="text: item"></td>
<td data-bind="text: quantity"></td>
<td><input type="button" data-bind="click:$root.deleteItem" value="X"></input>
</td>
</tr>
</tbody>
</table>
New to ReactJs - I have had a look at the documentation here and here but I am a bit confused.
So I have a component that creates several table rows according to the JSON data.
I am trying to make it so once a radio button is selected, the class of the parent <td> is set to 'success'. But at the moment all the rows with that column get the same class name.
var SearchResult = React.createClass({
getInitialState: function () {
return {
site: '',
address: '',
data: [],
checked: ''
};
},
onSiteChanged: function (e) {
this.setState({
site: e.currentTarget.value,
checked: 'success'
});
},
render: function () {
var resultRows = this.props.data.map(function (result) {
return (
<tr>
<td className={this.state.checked}>
<input type="radio" name="site_name"
value={result.SITE_NAME}
onChange={this.onSiteChanged}
key={result.id}/>{result.SITE_NAME}</td>
<td>
<input type="radio" name="address"
value={result.ADDRESS}
onChange={this.onAddressChanged} />{result.ADDRESS}</td>
</tr>
);
}, this);
return (
<table className="table table-hover table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{resultRows}
</tbody>
<tfoot>
<tr>
<td></td>
<td>{this.state.site}</td>
<td>{this.state.address}</td>
</tr>
</tfoot>
</table>
);
}
});
What is the best ReactJS way to proceed to make sure the selected result get the selected class name?
Thank you.
To modify values passed to classSet property React has special addon: React.addons.classSet. It is very handy when you are changing multiple different classes but in your case it can be usefull, too:
var SearchResult = React.createClass({
getInitialState: function () {
return {
site: '',
address: '',
checked: false,
data: [],
};
},
onSiteChanged: function (selected) {
this.setState({
site: selected.SITE_NAME,
checked: selected.id,
});
},
render: function () {
var resultRows = this.props.data.map(function (result) {
var cx = React.addons.classSet({
success: (this.state.checked === result.id)
});
return (
<tr key={result.id}>
<td className={cx}>
<input type="radio" name="site_name"
value={result.SITE_NAME}
onChange={this.onSiteChanged.bind(this, result)}
/>{result.SITE_NAME}</td>
<td>
<input type="radio" name="address"
value={result.ADDRESS}
onChange={this.onAddressChanged} />{result.ADDRESS}</td>
</tr>
);
}, this);
return (
<table className="table table-hover table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{resultRows}
</tbody>
<tfoot>
<tr>
<td></td>
<td>{this.state.site}</td>
<td>{this.state.address}</td>
</tr>
</tfoot>
</table>
);
}
});