How to set array in useForm and validate the length of value? - react-hook-form

I'm using react-hook-form.
What I wanna do is to push a value to an array and
validate the length of value.
This is defaultValue.
defaultValues: {
title: '',
role: '',
language: {source: '', target: []},
industry: '',
due_at: '',
content: '',
},
and this is input field that handles language.target.
<Controller
name="language.target"
control={control}
rules={{
required: true,
setValues: (v) => setValue([...getValues('language.target'), v.value]),
validate: (value) => {
return '';
},
}}
render={({field: {onChange}}) => (
<Select
options={languageIndex}
onChange={(value) => onChange(value.value)}
value={languageIndex.filter(
(item) => item.value === getValues('language.target')
)}
placeholder="Select"
/>
)}
/>
I tried this way to push a value like below and they didn't work..
setValues: (v) => setValue([...getValues('language.target'), v.value]),
setValues: (v) => [...getValues('language.target'), v.value],
also I have no idea how to validate the length of array.
If language.target.length is greater then 3,
I want to make it stop to set value.
If there's any good idea, please share with me! Thanks.

Related

nested dataIndex in Table of Ant Design

this is my code below
const columns = [
{
key: '1',
title: 'id',
dataIndex: 'id'
},
{
key: '2',
title: 'status',
dataIndex: 'status',
render: (text) => <a> {text} </a>
},
];
I wanna display data ( text/id ) like below code
const columns = [
{
key: '1',
title: 'id',
dataIndex: 'id'
},
{
key: '2',
title: 'status',
dataIndex: ['status', 'id'],
render: (text) => <a> {text} / {id} </a>
},
];
I tried to like this samples
1. dataIndex: ['status', 'id']
2. dataIndex: 'status.id'
but that doesn`t work. (version 4.14.0)
how can I display like that? please reply here. thanks.
I'll answer assuming what you pass to the dataSource is an array of objects which looks like below.
interface DataModel {
id: number;
status: string;
}
If so, you can use the second parameter in the render method which will have the record. Hence record.id will give you the id.
const columns = [
{
key: '1',
title: 'id',
dataIndex: 'id'
},
{
key: '2',
title: 'status',
dataIndex: ['status'],
render: (text: any, record: any) => <a> {text} / {record.id} </a>
},
];
try this solution
{
title: 'Name',
dataIndex: 'address',
key: 'name',
render: ({ city, street }) => (
<Typography>{`${city} ${street}`}</Typography>
),
},
try this
{
title: "Task",
dataIndex: ["task","name"]
},

Conflict on the React ant design table input total balance

Im tried to do some calculate part for my react ant design 4 table, i don't have idea for how to get when i entered value after get automatically calculate total and then submit. any onw know how to do that correctly.
Thanks
stack blitz here
This is my code part
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Book',
dataIndex: 'book',
key: 'book',
},
{
title: 'Pen',
dataIndex: 'pen',
key: 'pen',
},
{
title: 'Tools',
key: 'tools',
dataIndex: 'tools',
},
{
title: 'Total',
key: 'total',
dataIndex: 'total',
},
];
const data = [
{
key: '1',
name: 'John Brown',
book: <Form.Item name="book1" rules={[{required: true, message: " is required"}]}><Input style={{width: 150}}/></Form.Item>,
pen: <Form.Item name="oen1" rules={[{required: true, message: "is required"}]}><Input style={{width: 150}}/></Form.Item>,
tools: <Form.Item name="tools1" rules={[{required: true, message: " is required"}]}><Input style={{width: 150}}/></Form.Item>,
total:'00000'
},
];
const onFinish = values => {
console.log(values);
};
ReactDOM.render(
<div>
<Form name="control-hooks" onFinish={onFinish}>
<Table columns={columns} dataSource={data} />
<div>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</div>
</Form>
</div>, document.getElementById('container'));
I assumed the rows can be more than one. You can achieve this by:
You need a state. In react, in order to change something on the UI (e.g. total column) you need a state. Put your data array in state.
const [data, setData] = useState([ ... ])
You need to know which row the input was when you type in. You may add some distinction on input that is equal to row key. Here I suggest to put some number on the name of input:
<Form.Item name="book-1">...</Form.Item>
<Form.Item name="pen-1">...</Form.Item>
<Form.Item name="tools-1">...</Form.Item>
Use onValuesChange prop of the <Form> it triggers every time you type on the inputs and return the form values. With this, you can extract the number on input name and use that as a reference to know which row is about to change and perform setState.
I also suggest to use InputNumber instead of Input if you only need a number input.
Here is the working link. You can start/play around there if I did not hit what you want.
You may also look on antd table editable rows. This might be easiest to use than this

ANT design 4 table input filed validate

Im adding my react project for ant design4 table and ant design input fields. any one know to how can validate that input required
Thanks
stackablitz here
code here
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
render: tags => (
<>
{tags.map(tag => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
);
})}
</>
),
},
{
title: 'Action',
key: 'action',
render: (text, record) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
),
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: <input/>,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: <input/>,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: <input/>,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
const onFinish = values => {
console.log(values);
};
ReactDOM.render(
<div>
<Form name="control-hooks" onFinish={onFinish}>
<Table columns={columns} dataSource={data} /> <div><Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button> </Form.Item>
Just enclose the <input/> in <Form.Item> and use the rules prop of it. You can see all the possible rules here. I suggest use the <Input/> of antd and set a width on it.
const data = [
{
key: "1",
name: "John Brown",
age: (
<Form.Item
name="age1"
rules={[{ required: true, message: "Age is required" }]}
>
<Input style={{ width: 150 }} />
</Form.Item>
),
address: "New York No. 1 Lake Park",
tags: ["nice", "developer"],
},
...
];
see this working link

zf2 form disable select option(s)

Is it possible to disable the options in a select element?
I have a form with a select element that by default has a lot of options available. During form creation, depending on information retrieved from the database, i would like to disable certain options.
Some research came up with
$form->get('selectElement')->setAttribute("disabled", array(0, 1, 2));
...which should disable the first 3 options, but unfortunately does not.
You must use the setAttribute() method to set the attributes of your select element, not its options. For this, you should use setValueOptions():
$myOptions = $form->get('selectElement')->getValueOptions();
foreach ([0, 1, 2] as $value) {
$myOptions [$value]['disabled'] = true ;
}
$form->get('selectElement')->setValueOptions($myOptions);
$myOptionsmust be an array of options:
[
[
'label' => 'My first option',
'disabled' => false,
'value' => 1
],
[
'label' => '2nd option',
'disabled' => false,
'value' => 2
],
[
'label' => '3rd option disabled',
'disabled' => true,
'value' => 3
],
]

How can I use a custom sortFunction with a Grails gui:datatable tag?

I have a datatable in Grails with several sortable columns. Unfortunately, the sort is case-sensitive by default, such that "Zed" is shown before "alice". So I want to add a custom case-insensitive sort function. I'll start by sorting the username column in this manner.
I have read about the sortOptions and sortFunction at http://developer.yahoo.com/yui/datatable/ but I can't seem to get it to work.
I added the following JavaScript to list.gsp:
var caseInsensitiveSortFunction = function(a, b, desc, field) {
// See http://developer.yahoo.com/yui/datatable/ and look for 'sortFunction'
// Set this function name as the sortFunction option
// Deal with empty values
if (!YAHOO.lang.isValue(a)) {
return (!YAHOO.lang.isValue(b)) ? 0 : 1;
} else if (!YAHOO.lang.isValue(b)) {
return -1;
}
return YAHOO.util.Sort.compare(String(a).toLowerCase(), String(b).toLowerCase(), desc);
};
And here is the datatable definition on that same page:
<gui:dataTable id="userTable"
controller="user" action="listJSON"
rowsPerPage="20"
sortedBy="username"
columnDefs="[
[key:'username', label:'Username', resizeable: false, sortable: true, sortOptions: { sortFunction: 'caseInsensitiveSortFunction' }],
[key:'email', label:'Email', resizeable: false, sortable: true],
[key:'firstName', label:'First Name', resizeable: false, sortable: true],
[key:'lastName', label:'Last Name', resizeable: false, sortable: true],
[key:'enabled', label:'Enabled', resizeable: false, sortable: true],
[key:'accountLocked', label:'Locked', resizeable: false, sortable: true],
[key:'roleDescription', label:'Role', resizeable: false, sortable: true]
]"
draggableColumns="true"
rowClickNavigation="true"
paginatorConfig="[
template:'{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {CurrentPageReport}',
pageReportTemplate:'{totalRecords} total record(s)',
alwaysVisible:true,
containers:'dt-paginator'
]"/>
<div id="dt-paginator" class="yui-skin-sam yui-pg-container"></div>
Changing the 'username' key to the following (sans quotes) does not help.
[key:'username', label:'Username', resizeable: false, sortable: true, sortOptions: { sortFunction: caseInsensitiveSortFunction }],
Both approaches create the following source. Note that the sortOptions for the username is blank.
<div id="dt_div_userTable"></div>
<script>
YAHOO.util.Event.onDOMReady(function () {
var DataSource = YAHOO.util.DataSource,
DataTable = YAHOO.widget.DataTable,
Paginator = YAHOO.widget.Paginator;
var userTable_ds = new DataSource('/admin/gpupUser/listJSON?');
userTable_ds.responseType = DataSource.TYPE_JSON;
userTable_ds.connMethodPost=true;
userTable_ds.responseSchema = {
resultsList : 'results',
fields : ["username","email","firstName","lastName","enabled","accountLocked","roleDescription","dataUrl"],
metaFields : {
totalRecords: 'totalRecords'
}
};
userTable_ds.doBeforeCallback = function(oRequest, oFullResponse, oParsedResponse, oCallback) {
return GRAILSUI.util.replaceDateStringsWithRealDates(oParsedResponse);
};
var userTable_paginator = new Paginator(
{'template': '{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {CurrentPageReport}',
'pageReportTemplate': '{totalRecords} total record(s)',
'alwaysVisible': true,
'containers': 'dt-paginator',
'rowsPerPage': 20}
);
var registerEditorListener = function(editor, field, url,successCallback,failureCallback) {
editor.subscribe("saveEvent", function(oArgs) {
GRAILSUI.userTable.loadingDialog.show();
var editorCallback = {
success: successCallback,
failure: function(o) {
// revert the cell value
GRAILSUI.userTable.updateCell(oArgs.editor.getRecord(), field, oArgs.oldData);
// alert user
if (failureCallback)
failureCallback(o);
else
alert('Received an error during edit: ' + o.responseText);
}
};
YAHOO.util.Connect.asyncRequest('POST', url, editorCallback, 'id=' + oArgs.editor.getRecord().getData('id') + '&field=' + field + '&newValue=' + oArgs.newData);
});
};
var myColumnDefs = [{'key': 'username',
'label': 'Username',
'resizeable': false,
'sortable': true,
'sortOptions': }, {'key': 'email',
'label': 'Email',
'resizeable': false,
'sortable': true}, {'key': 'firstName',
'label': 'First Name',
'resizeable': false,
'sortable': true}, {'key': 'lastName',
'label': 'Last Name',
'resizeable': false,
'sortable': true}, {'key': 'enabled',
'label': 'Enabled',
'resizeable': false,
'sortable': true}, {'key': 'accountLocked',
'label': 'Locked',
'resizeable': false,
'sortable': true}, {'key': 'roleDescription',
'label': 'Role',
'resizeable': false,
'sortable': true}, {'key': 'dataUrl',
'type': 'dataDrillDown',
'hidden': true}];
GRAILSUI.userTable = new GRAILSUI.DataTable('dt_div_userTable', myColumnDefs, userTable_ds, '', {
initialRequest : 'max=20&offset=0&sort=username&order=asc&',
paginator : userTable_paginator,
dynamicData : true,
sortedBy : {key: "username", dir: YAHOO.widget.DataTable.CLASS_ASC},
'draggableColumns': true,
'selectionMode': 'single',
'rowClickNavigate': false,
'rowClickMode': 'navigate',
'formatter': 'text'
});
// Update totalRecords on the fly with value from server
GRAILSUI.userTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
oPayload.totalRecords = oResponse.meta.totalRecords;
return oPayload;
};
// Set up editing flow
var highlightEditableCell = function(oArgs) {
var elCell = oArgs.target;
if(YAHOO.util.Dom.hasClass(elCell, "yui-dt-editable")) {
this.highlightCell(elCell);
}
};
GRAILSUI.userTable.subscribe("cellMouseoverEvent", highlightEditableCell);
GRAILSUI.userTable.subscribe("cellMouseoutEvent", GRAILSUI.userTable.onEventUnhighlightCell);
GRAILSUI.userTable.subscribe("cellClickEvent", GRAILSUI.userTable.onEventShowCellEditor);
});
</script>
<div id="dt-paginator" class="yui-skin-sam yui-pg-container"></div>
Is there any way to get the datatable to use a custom sortFunction when configured as a tag?
In listJSON action, add ignoreCase: true parameter to list(). See doc. It's probably the only easy way.
You cannot push a totally custom function from Javascript level to database level, if you're going to support paging - custom function will sort current page only, but paging will be based on default (by id) ordering. In other words, custom function works correctly for no more then 1-page tables.
You can customize sorting to certain extent if you use a Criteria or SQL in listJSON action - but still, you're limited to Hibernate or SQL level.
After digging into the code base, I finally realized that the sorting was being done on the server side, so I was able to address the issue there.

Resources