how to iterate over an array in react-toolbox DropDown - react-toolbox

Initially i was using simple html select box in reactjs and i iterated my array coming as props in child element as
<select onChange={this.getOccasion}>
<option value="states">States</option>
{
this.props.holidays.map(function(holidays,i) {
return <option key={i}
value={holidays.state}>{holidays.state}</option>;
})
}
</select>
But i have no idea where to iterate over my array in react-toolbox Dropdown.I tried following
<Dropdown
auto
onChange={this.getOccasion}
source={this.props.holidays}
value={this.props.holidays.state}
/>

You need to have the dropdown source array to be in a certain format.
const countries = [
{ value: 'EN-gb', label: 'England' },
{ value: 'ES-es', label: 'Spain'},
{ value: 'TH-th', label: 'Thailand' },
{ value: 'EN-en', label: 'USA'}
];
Check RT dropdown component.
So, you could do like,
const holidays = this.props.holidays.map(holiday => ({
value: holiday.state,
label: holiday.state
}));
<Dropdown
auto
onChange={this.getOccasion}
source={holidays}
value={this.state.someVariable}
/>

Related

antd Form.Item accepts only one child

I've created a little Fiddle to illustrate the issue: https://stackblitz.com/edit/react-avejvc-mmhqda?file=index.js
This form works:
<Form initialValues={{ surname: 'Mouse'}}>
<Form.Item name="surname">
<Input />
</Form.Item>
</Form>
This form doesn't:
<Form initialValues={{ surname: 'Mouse'}}>
<Form.Item name="surname">
<Input />
{null}
</Form.Item>
</Form>
The only difference is that the Form.Item in the second form has two children.
Is there an intention behind this?
In case anyone wonders why I am asking. So sth like this is breaking the form:
<Form.Item name={name}>
{type==="string" && <Input />}
{type==="integer" && <InputNumber />}
</Form.Item>
The official documentation here gives examples of using multiple children in one Form.Item.
<Form.Item label="Field">
<Form.Item name="field" noStyle><Input /></Form.Item> // that will bind input
<span>description</span>
</Form.Item>
You appear to have a problem with what you are putting in the Form.Item, ie. {null} may not be allowed.
I found a solution and have a better understanding now of what is going on.
From the docs (https://ant.design/components/form/#Form.Item):
After wrapped by Form.Item with name property, value(or other property defined by valuePropName) onChange(or other property defined by trigger) props will be added to form controls, the flow of form data will be handled by Form
There is a working example in the docs too, here is the codepen: https://codepen.io/pen?&editors=001
const { useState } = React;;
const { Form, Input, Select, Button } = antd;
const { Option } = Select;
const PriceInput = ({ value = {}, onChange }) => {
const [number, setNumber] = useState(0);
const [currency, setCurrency] = useState('rmb');
const triggerChange = (changedValue) => {
onChange?.({
number,
currency,
...value,
...changedValue,
});
};
const onNumberChange = (e) => {
const newNumber = parseInt(e.target.value || '0', 10);
if (Number.isNaN(number)) {
return;
}
if (!('number' in value)) {
setNumber(newNumber);
}
triggerChange({
number: newNumber,
});
};
const onCurrencyChange = (newCurrency) => {
if (!('currency' in value)) {
setCurrency(newCurrency);
}
triggerChange({
currency: newCurrency,
});
};
return (
<span>
<Input
type="text"
value={value.number || number}
onChange={onNumberChange}
style={{
width: 100,
}}
/>
<Select
value={value.currency || currency}
style={{
width: 80,
margin: '0 8px',
}}
onChange={onCurrencyChange}
>
<Option value="rmb">RMB</Option>
<Option value="dollar">Dollar</Option>
</Select>
</span>
);
};
const Demo = () => {
const onFinish = (values) => {
console.log('Received values from form: ', values);
};
const checkPrice = (_, value) => {
if (value.number > 0) {
return Promise.resolve();
}
return Promise.reject(new Error('Price must be greater than zero!'));
};
return (
<Form
name="customized_form_controls"
layout="inline"
onFinish={onFinish}
initialValues={{
price: {
number: 0,
currency: 'rmb',
},
}}
>
<Form.Item
name="price"
label="Price"
rules={[
{
validator: checkPrice,
},
]}
>
<PriceInput />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, mountNode);

How to use Radio groups inside Antd table?

I want to do this: each row is a Radio group, each cell is a Radio button, like the picture:
An example of Radio group is like:
<Radio.Group onChange={this.onChange} value={this.state.value}>
<Radio value={1}>A</Radio>
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</Radio.Group>
But I don't know how to add a Radio group to wrap each Antd table row?
My current code is:
renderTable() {
let columns = [];
columns.push(
{
title: '',
dataIndex: 'name',
key: 'name',
width: '45vw',
},
);
this.props.task.options.forEach((option, i) => {
columns.push(
{
title: option,
dataIndex: option,
key: option,
className: 'choice-table-column',
render: x => {
return <Radio value={0} />
},
},
);
});
let rowHeaders = [];
this.props.task.extras.forEach((extra, i) => {
rowHeaders.push(
{"name": `${i + 1}. ${extra}`},
);
});
// How can I pass a className to the Header of a Table in antd / Ant Design?
// https://stackoverflow.com/questions/51794977/how-can-i-pass-a-classname-to-the-header-of-a-table-in-antd-ant-design
const tableStyle = css({
'& thead > tr > th': {
textAlign: 'center',
},
'& tbody > tr > td': {
textAlign: 'center',
},
'& tbody > tr > td:first-child': {
textAlign: 'left',
},
});
return (
<div>
<Table className={tableStyle} columns={columns} dataSource={rowHeaders} size="middle" bordered pagination={false} />
</div>
);
}
I don't think it is possible to use radio group for each row, however you can achieve it in a traditional way.
Here is code sample
https://codesandbox.io/s/goofy-benz-12kv5
class App extends React.Component {
state = {
task: { options: [1, 2, 3, 4, 5], extras: [6, 7, 8, 9, 10] },
selected: {}
};
onRadioChange = e => {
let name = e.currentTarget.name;
let value = e.currentTarget.value;
this.setState({
...this.state,
selected: { ...this.state.selected, [name]: value }
});
};
onSubmit = () => {
console.log(this.state.selected);
this.setState({
...this.state,
selected: {}
});
};
render() {
let columns = [];
columns.push({
title: "",
dataIndex: "name",
key: "name",
width: "45vw"
});
this.state.task.options.forEach((option, i) => {
columns.push({
title: option,
key: option,
render: row => {
return (
<input
type="radio"
checked={this.state.selected[row.name] == option}
onChange={this.onRadioChange}
name={row.name}
value={option}
/>
);
}
});
});
let rowHeaders = [];
this.state.task.extras.forEach((extra, i) => {
rowHeaders.push({ name: `${i + 1}.${extra}` });
});
return (
<div>
<Button onClick={this.onSubmit} type="primary">
{" "}
Submit
</Button>
<Table
columns={columns}
dataSource={rowHeaders}
size="middle"
bordered
pagination={false}
/>
<Tag color="red">Selected options</Tag>
<br />
{JSON.stringify(this.state.selected)}
</div>
);
}
}
hi there i had the same problem and base on new updates on antd this way of using is easier
<Table
rowSelection={{
type: "radio",
getCheckboxProps: (record) => {
console.log("record", record);
},
}}
pagination={{ hideOnSinglePage: true }}
columns={columns}
dataSource={data}
/>
example : https://ant.design/components/table/#components-table-demo-row-selection
for hiding table header : https://newbedev.com/javascript-antd-table-hide-table-header-code-example
hope its usefull

how can i get Select option value in antd

I have two select drop downs. If I click on One select option, it should be select and after click, without clicking second dropdown, i am not suppose to click update button. It should be show error.
import React from 'react'
import ReactDOM from 'react-dom'
import { Select, Button } from 'antd';
const Option =Select.Option
class SelectOption extends React.Component{
handleTeacherChange=(value)=>{
console.log(value)
}
handleCourseChange=(value)=>{
console.log(value)
}
render()
{
return(
<div align="center">
<div>
<h2>Shishu Bharathi</h2>
<label>Teacher List :</label>
<Select defaultValue="Select" style={{ width: 120 }} onChange={this.handleTeacherChange}>
<Option value="Vikram">Vikram</Option>
<Option value="Ramesh">Ramesh</Option>
</Select>
<label>Course List :</label>
<Select defaultValue="Select" style={{ width: 120 }} onChange={this.handleCourseChange}>
<Option value="cul1a">CUL1A</Option>
<Option value="cul1b">CUL1B</Option>
</Select>
</div>
<br></br>
<br></br>
<Button >Update</Button>
</div>
)
}
}
export default SelectOption
Use validateFields to check if a field is empty or not.
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Select, Button, Form } from "antd";
const Option = Select.Option;
class SelectOption extends React.Component {
handleTeacherChange = value => {
console.log(value);
// this.props.form.validateField(["Dropdown2"]);
};
handleCourseChange = value => {
console.log(value);
// this.props.form.validateField(["Dropdown1"]);
};
updateClick = () => {
const { getFieldValue, validateFields } = this.props.form;
const dropdown1Value = getFieldValue("Dropdown1");
const dropdown2Value = getFieldValue("Dropdown2");
if (dropdown1Value === "Select" && dropdown2Value !== "Select") {
validateFields(["Dropdown1"]);
}
if (dropdown1Value !== "Select" && dropdown2Value === "Select") {
validateFields(["Dropdown2"]);
}
};
render() {
const { getFieldDecorator } = this.props.form;
return (
<div align="center">
<div>
<h2>Shishu Bharathi</h2>
<label>Teacher List :</label>
<Form.Item>
{getFieldDecorator("Dropdown1", {
initialValue: "Select",
rules: [
{ required: true, message: "Select the teacher" },
{
validator: (rule, value, callback) => {
console.log("value", value);
if (value === "Select") {
callback("Select the teacher");
}
callback();
}
}
]
})(
<Select
style={{ width: 120 }}
onChange={this.handleTeacherChange}
>
<Option value="Vikram">Vikram</Option>
<Option value="Ramesh">Ramesh</Option>
</Select>
)}
</Form.Item>
<label>Course List :</label>
<Form.Item>
{getFieldDecorator("Dropdown2", {
initialValue: "Select",
rules: [
{ required: true, message: "Select the course" },
{
validator: (rule, value, callback) => {
if (value === "Select") {
callback("Select the course");
}
callback();
}
}
]
})(
<Select style={{ width: 120 }} onChange={this.handleCourseChange}>
<Option value="cul1a">CUL1A</Option>
<Option value="cul1b">CUL1B</Option>
</Select>
)}
</Form.Item>
</div>
<br />
<br />
<Button onClick={this.updateClick}>Update</Button>
</div>
);
}
}
const A = Form.create()(SelectOption);
ReactDOM.render(<A />, document.getElementById("container"));
Here is a working demo :CodeSandbox
If you want show error when without clicking second dropdown, you need wrap it using formItem and validate it. Like follow code:
<FormItem
{...formItemLayout}
label={'month'}
>
{this.props.form.getFieldDecorator('loanMonth', {
initialValue: 3,
rules: [{
required: true, message: 'please select month!',
}],
})(
<Select>
{
this.formInitData &&
toJS(this.formInitData).loanMonthList.map((data) => {
return (
<Option value={data.key}>{data.value}</Option>
);
})
}
</Select>,
)}
</FormItem>
using the rules: [{required: true, message: 'please select month!'}] to get it.
Suggesting you see https://ant.design/components/form/

Apply filter on knockout reduce function

I have below code in my razor view to populate radio button,
<!-- ko foreach: { data: ko.unwrap(cars).reduce(function (res, v, i) { res[i%2].push(v); return res; }, [[],[]]), as: 'cars' } -->
<div data-bind="foreach: cars">
<label class="car">
<div>
<input type="radio" name="Carinfo.Name" data-bind="checked: $root.carId, checkedValue: Id, value: Id"><span data-bind="text: model"></span
</div>
</label>
</div>
<!-- /ko -->
Trying to understand what reduce function is doing here
ko.unwrap(cars).reduce(function (res, v, i) { res[i%2].push(v); return res; }
Can I filter cars observable array (like v.Make == 'Honda'), inside reduce function and returned filtered cars to the DOM to populate radio button
First, you want to remove all this logic from the view and move it to a viewModel.
This will give you
proper intellisense (auto complete, hovering functions gives info on them and all these IDE goodness).
readability: you view will just look like that:
<!-- ko foreach: { data: filteredCars -->
Testability. You will be able to write unit tests on that view model property. While testing the view is particularly hard.
Now your answer:
Trying to understand what reduce function is doing here
ko.unwrap(cars).reduce(function (res, v, i) { res[i%2].push(v); return
res; }
ko.unwrap is a function which fetches the actual value of on object, no matter if it's observable or not. For example:
console.log(ko.unwrap(ko.observableArray([1, 2, 3])));
console.log(ko.unwrap([1, 2, 3]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
array reduce runs a callback against an array, and reduces all values inside an accumulator. To understand what this example is doing, let's run it on an easier example:
var cars = ["honda", "renault", "ford", "toyota", "volkswagen", "chevrolet", "volvo"];
var splitted = cars.reduce(function (res, v, i) {
res[i%2].push(v); return res;
}, [[],[]]);
console.log(splitted);
It's basically splitting your array of cars into two arrays. First array with cars having even indexes, and second with odd indexes.
Can I filter cars observable array (like v.Make == 'Honda'), inside
reduce function and returned filtered cars to the DOM to populate
radio button
Yes you can: again, a simple fiddle:
// let's say this observable comes from another VM
var cars = ko.observableArray([{
maker: "honda",
country: "japan"
}, {
maker: "renault",
country: "france"
}, {
maker: "ford",
country: "us"
}, {
maker: "toyota",
country: "japan"
}, {
maker: "volkswagen",
country: "germany"
}, {
maker: "chevrolet",
country: "us"
}, {
make: "volvo",
country: "sweden"
}]);
var viewModel = function() {
this.japaneseCars = ko.computed(function() {
return ko.unwrap(cars).reduce(function(result, v, i) {
if (v.country === "japan") {
result.push(v.maker);
}
return result;
}, []);
}, this);
};
var vm = new viewModel();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: japaneseCars">
<input type="radio" name="cars" data-bind="attr: { value: $data }">
<span data-bind=" text: $data " />
<br />
</div>

Bootstrap Select2 version 3.5.2

Can anyone help me with an working example of below scenario?
Select2 option with loading data through array with default selected value and in case of edit mode changing the selected value according to users requirement. This is my code but it is not working.
<input type="hidden" id="selectCountry" class="selectCountry" style="width:100%" />
JS
var displayOptions = [{id:'1',text:'test'},{id:'2',text:'test1'},
{id:'3',text:'test2'},{id:'4',text:'test3'},
{id:'5',text:'Do not display'}]
$(".selectDisplayOptions").select2({
data: displayOptions,
minimumResultsForSearch: -1,
dropdownAutoWidth: true
});
I tried initselection but it cause problem when I try to selected different value in edit case of my application.
JS code for selecting different value in case of edit
$('.selectDisplayOptions').val(2);
You should call your select class or ID look the documentation:
https://select2.github.io/examples.html
And you should take care the way that you use to set the value in your select example:
<select class="selectDisplayOptions">
<option value="0">Boy</option>
<option value="1">Girl</option>
</select>
$('.selectDisplayOptions').val('1'); // This will bring back Girl.
$('.selectDisplayOptions').val('Girl'); // This will bring back Girl too.
var data = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
$(".js-example-data-array").select2({
data: data
})
$(".js-example-data-array-selected").select2({
data: data
})
<select class="js-example-data-array-selected"></select>
<select class="js-example-data-array-selected">
<option value="2" selected="selected">duplicate</option>
</select>
Regards,

Resources