ReferenceInput with null value through ra-data-graphql - react-admin

"react-admin": "^4.1.3"
I have the following field definition on the <Create> page -
<TextInput source="name"/>
<TextInput source="description"/>
<ReferenceInput label="Parent" source="parent_id" reference="categories">
<SelectInput optionText="name"/>
</ReferenceInput>
With this setup when the value for the select input is left in the blank state it results in the following variables being sent as part of the payload
{
"objects": {
"name": "Some Value",
"description": "Description",
"parent_id": ""
}
}
And results in an error
{"errors":[
{"extensions":
{
"path":"$.selectionSet.insert_categories.args.objects",
"code":"data-exception"
},
"message":"invalid input syntax for type integer: \"\""
}
]}
Which makes sense because parent_id should be null and not included in the variables array.
As a workaround I have tried adding emptyValue={null} to the <SelectInput/> component. The only change when adding this is that a javascript error is thrown when the empty row is selected in the browser.
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components.
The payload remains the same with "parent_id": "" still part of the variables array.
What do I need to do in order to properly setup a <ReferenceInput/> that allows null integer values to be submitted.

Related

Mule 4: Replace recurring node value in original payload

I have a recurring node/array in the JSON payload. I need to use value of the wonumber to call another service and the value from this service response has to be used to replace a code value on original message.
{
"element1": "text1",
"element2": "text2",
"element3": "text3",
"InvoiceItemDTO": [
{
"code": "",
"itemNo": "1",
"wonumber": 123
},
{
"code": "",
"itemNo": "2",
"wonumber": 456
}
]
}
The service response will give value for code field, which has to be copied back on original payload code value.
I have applied for each loop on the recurring node to make the call to service for each block in ItemDTO. But I am concerned about putting service response value field back on the original payload at the same index for which the service call was made.
If service call returns code value as abc1, def2 for above payload, then expected final payload is:
{
"element1": "text1",
"element2": "text2",
"element3": "text3",
"InvoiceItemDTO": [
{
"code": "abc1",
"itemNo": "1",
"wonumber": 123
},
{
"code": "def2",
"itemNo": "2",
"wonumber": 456
}
]
}
Any recommendations on how this can be achieved?
the for-each scope does not change the payload. If you want to retain some information gathered during execution of for-each you will need to store that data in a variable. As per the official doc
Every execution of the For Each scope starts with the variables and values from the previous execution of the block. New variables or modifications to existing variables that take place when processing one element are visible during the processing of another element. These changes to variables continue to be available outside the For Each scope.
For your use case you can do the following (Just a pseudo code)
Collect all unique wonumber in an array and store it in a variable
<set-variable variableName="wonumbers" value="#[payload.InvoiceItemDTO.wonumber distinctBy $]"/>
Loop through this variable in the for-each scope
After collecting the code for the wonumber store that as a map in a variable so that you can access it later.
<foreach collection="#[vars.wonumbers]">
<set-variable variableName="currentWonumber" value="#[payload]" />
<do-your-thing.... />
<set-variable variableName="wonumbersToCodeMapping" value="#[(vars.wonumbersToCodeMapping default {}) ++ (vars.currentWonumber): payload.code //however you are getting the code]"/>
</foreach>
Using the wonumbersToCodeMapping you can update the payload using update operator
%dw 2.0
output json
---
payload update {
case .InvoiceItemDTO ->
$ map ((item) -> item update {
case .code -> vars.wonumbersToCodeMapping[item.wonumber as String]
})
}

GraphQL: Cannot return null for non-nullable field

I'd created gql fragment as below without photo part at first.
And then later I added photo {id} part on this fragment.
export const COMMENT_FRAGMENT = gql`
fragment CommentFragment on Comment {
id
user {
username
avatar
}
payload
isMine
createdAt
photo {
id
}
}
`;
But it shows error message:
"message": "Cannot return null for non-nullable field Comment.photo.",
"path": Array [
"seeFeed",
1,
"comments",
0,
"photo",
],
},
Strange thing is I checked several times that there's no null or empty field of photo.id of comments.
As you can see, Comment field has photo[] and photo has 'id', which means my fragment has no error.
When I searched about it people say it is not my query problem, but something about migration?
Can you help me? :(

How to find if element exists in an array in react-native

I am trying to render an element after checking whether there is a string e.g. "abc" present in an array. I have tried using various different functions like array.find(), array.includes(), array.some() While I do so, it gives me an error -
TypeError: null is not an object(evaluating 'o.includes')
Below is the piece of code that I am using inside render function. "abc" is the array where I am trying to check whether string "a" exists in that array, if it does then display that ExpandedHeader element.
PS: I am new to react-native.
<View>
{abc.includes("a") && <ExpandedHeader title={"Got it"}
expanded={this.state.riskRatingExpanded}
onPress={() => {this.setState({
riskRatingExpanded :!this.state.riskRatingExpanded,
basicDetailsExpanded : false,
envProfileExpanded : false,
nwswProfileExpanded : false,
additionalInfoExpanded : false,
scoresExpanded : false,
});
}}
/>}
</View>
But instead, if I do the below it works -
<View>
{abc != null && <ExpandedHeader title={abc[0]}
expanded={this.state.riskRatingExpanded}
onPress={() => {this.setState({
riskRatingExpanded :!this.state.riskRatingExpanded,
basicDetailsExpanded : false,
envProfileExpanded : false,
nwswProfileExpanded : false,
additionalInfoExpanded : false,
scoresExpanded : false,
});
}}
/>}
</View>
Your render function runs before your array data is present and initially your array data is null,
make sure you initialise your abc state as array first,
state = {
abc: []
}
with this, your first code should work.

How to set defaultValue for multi select?

So, I need to pass defaultValue to a react-select component with enabled multi select. I've tried everything I could think of: array of strings, array of objects, string, etc... Nothing seems to work.
I'm also using the getOptionLabel and getOptionValue, might they be the cause for all this mess?
If you refer to react-select documentation, the way to set defaultValue to multiple value select:
<Select
defaultValue={[colourOptions[2], colourOptions[3]]}
isMulti
name="colors"
options={colourOptions}
className="basic-multi-select"
classNamePrefix="select"
/>
The structure of options is
[
{
label: <string>,
value: <string>,
}
]
Working example here.
There is an alternate way to use value as your defaultValue.
In my case I have used "id" and "industry" instead of "label" and "value"
this.state = {
interested_industries: [{id:"ANY", industry:"ANY"}]
}
And in Select component:-
<Select
name="interested_industries"
options={industries}
value={interested_industries}
getOptionLabel={ x => x.id}
getOptionValue={ x => x.industry}
onChange={this.handleSelect}
isMulti
/>
defaultValue accepts an object or array of objects.
here an object can be like this :
defaultValue = {{ value: 0, label: "John" }}
This is also one way:
defaultValue = { array1[0] }
If you want array of objects for multiple options (isMulti) you can do this:
defaultValue = { array1.map(ele => ele) }
Where array1 is an array of objects.
array1 = [
{ label: "John", value: 0 },
{ label: "Indiana", value: 1 },
{ label: "Stark", value: 2 },
];
This solution worked for me. I hope this helps you too.
You can set defaultValue without index
<Select
defaultValue={existingItems}
onChange={(option) => onChangeSelect(option)}
closeMenuOnSelect={false}
components={animatedComponents}
isMulti={true}
options={options}
/>
But for this to work you need await loading items from defaultValue if you loading from server
For Example my full code
{!kindsByRestaraunt.loading ? (
<Select
defaultValue={existingItems}
onChange={(option) => onChangeSelect(option)}
closeMenuOnSelect={false}
components={animatedComponents}
isMulti={true}
options={options}
/>
): ""}
According to React documentation, you can do this:
<select multiple={true} value={['B', 'C']}>
Where B, C are the default value you want to have selected.

Collapsing a group using Google Sheets API

So as a workaround to difficulties creating a new sheet with groups I am trying to create and collapse these groups in a separate call to batchUpdate. I can call request an addDimensionGroup successfully, but when I request updateDimensionGroup to collapse the group I just created, either in the same API call or in a separate one, I get this error:
{
"error": {
"code": 400,
"message": "Invalid requests[1].updateDimensionGroup: dimensionGroup.depth must be \u003e 0",
"status": "INVALID_ARGUMENT"
}
}
But I'm passing depth as 0 as seen by the following JSON which I send in my request:
{
"requests":[{
"addDimensionGroup":{
"range":{
"dimension":"ROWS",
"sheetId":0,
"startIndex":2,
"endIndex":5}
}
},{
"updateDimensionGroup":{
"dimensionGroup":{
"range": {
"dimension":"ROWS",
"sheetId":0,
"startIndex":2,
"endIndex":5
},
"depth":0,
"collapsed":true
},
"fields":"*"
}
}],
"includeSpreadsheetInResponse":true}',
...
I'm not entirely sure what I am supposed to provide for "fields", the documentation for UpdateDimensionGroupRequest says it is supposed to be a string ("string ( FieldMask format)"), but the FieldMask definition itself shows the possibility of multiple paths, and doesn't tell me how they are supposed to be separated in a single string.
What am I doing wrong here?
The error message is actually instructing you that the dimensionGroup.depth value must be > 0:
If you call spreadsheets.get() on your sheet, and request only the DimensionGroup data, you'll note that your created group is actually at depth 1:
GET https://sheets.googleapis.com/v4/spreadsheets/{SSID}?fields=sheets(rowGroups)&key={API_KEY}
This makes sense, since the depth is (per API spec):
depth numberThe depth of the group, representing how many groups have a range that wholly contains the range of this group.
Note that any given particular DimensionGroup "wholly contains its own range" by definition.
If your goal is to change the status of the DimensionGroup, then you need to set its collapsed property:
{
"requests":
[
{
"updateDimensionGroup":
{
"dimensionGroup":
{
"range":
{
"sheetId": <your sheet id>,
"dimension": "ROWS",
"startIndex": 2,
"endIndex": 5
},
"collapsed": true,
"depth": 1
},
"fields": "collapsed"
}
}
]
}
For this particular Request, the only attribute you can set is collapsed - the other properties are used to identify the desired DimensionGroup to manipulate. Thus, specifying fields: "*" is equivalent to fields: "collapsed". This is not true for the majority of requests, so specifying fields: "*" and then omitting a non-required request parameter is interpreted as "Delete that missing parameter from the server's representation".
To change a DimensionGroup's depth, you must add or remove other DimensionGroups that encompass it.