Redux Form FieldArray parse and format - redux-form

When using a FieldArray the data are parsed and stored in Redux as an array of objects. In my case:
[
{
email: "something#domain.ext"
},
{
email: "another#domain.ext"
}
]
I would like to use the parse and format property to store in redux an array of strings instead of objects like so:
[
'something#domain.ext',
'another#domain.ext'
]
Is this possible?

Found out i just needed to set onClick={() => fields.push()} on the Add email button. That would not create an object but just an array of plain strings.

Related

How to convert lavavel collection to square bracket collection

I have laravel livewire collection as below.
[
{
"date":"2021.09.01-0:00",
"open":110.177,
"close":110.175,
"low":110.172,
"high":110.18
},
{
"date":"2021.09.01-0:01",
"open":110.175,
"close":110.171,
"low":110.169,
"high":110.175
},
{
"date":"2021.09.01-0:02",
"open":110.171,
"close":110.173,
"low":110.17,
"high":110.176
}
]
I would like to convert them into form of square bracket collection without key name as below .
$data = [
['2021.09.01-0:00',110.177,110.175,110.172,110.18],
['2021.09.01-0:01',110.175,110.171,110.169,110.175],
['2021.09.01-0:02',110.171,110.173,110.17,110.176]
];
Any advice or guidance on this would be greatly appreciated, Thanks.
You can use collection map method:
The map method iterates through the collection and passes each value to the given callback. The callback is free to modify the item and return it
https://laravel.com/docs/8.x/collections#method-map
$expectData = $collection->map(fn($item) => [$item-> date, $item->open,...])
I am not sure what the original data is but you can map over the collection and pull the values; if Eloquent Models:
$data->map(fn ($v) => array_values($v->toArray()))
Would depend upon how you got that original Collection for how it would end up in this scenario.
If you need to restrict what attributes and the order of them returned you can use only on the model:
fn ($v) => array_values($v->only(['date', ...]))

check if an array contains a string with Yup

I'm trying to make a field in a form required if my array contains a certain string.
For example, the field 'spouseName' should be required if the array familyMembers contains 'spouse'. Is it possible to use the .when() function to check the values in array? I'm using it to check the value of strings in other parts of the forms like this:
jobTitle: Yup.string().when("jobStatus", {
is: "employed",
then: Yup.string().required(requiredError)
})
is there a way to do something like:
spouseName: Yup.string().when("familyMembers", {
contains: "spouse",
then: Yup.string().required(requiredError)
})
Instead of passing the second parameter as a object, you could pass it as a function that receives the value of the field from the first parameter (in your case, the value of familyMembers) and the schema to be modified (in your case, add required).
You can see how to do this in the docs mixed.when (It's the last example).
e.g. from the docs
yup.object({
isBig: yup.boolean(),
count: yup.number().when('isBig', (isBig, schema) => {
return isBig ? schema.min(5) : schema.min(0);
}),
});
So in your case, it should be something like
spouseName: Yup.string().when("familyMembers", (familyMembers, schema) => {
// if it includes 'spouse'
return familyMembers.includes('spouse') ?
Yup.string().required(requiredError) : // add required validation
schema; // don't change anything
}),
})
You can do other logic inside the function and also return diferent schema types.

How to fix an array input value with Laravel / Vue JS

This is a Laravel 5 project.
I have a standard form being submitted. I am trying to send the ID's of each account clicked from the results of the search function added within the vue component.
The details clicked are then stored in a hidden form input called 'grantedUsers'. This has the ability to store more than one value. So I've used the name grantedUsers[].
Upon submitting the form to the backend, I've DD'ed the value and it's showing all the values but in one index instead of separate indexes for each. Making it way more difficult to process data efficiently.
I'm obviously submitting the value incorrectly to the hidden input. Any assistance would be appreciated in splitting each ID into separate indexes.
Code
<input type="hidden" name="grantedUsers[]" :value="hiddenData">
//hiddenData is an empty array at initialisation.
data() {
return {
keywords: null,
results: [],
granted: [],
hiddenData: []
};
},
addUser(result) {
this.granted.push(result);
this.results.splice(this.results.indexOf(result), 1);
this.hiddenData.push(result.id);
},
removeUser(grantee) {
this.results.push(grantee);
this.granted.splice(this.granted.indexOf(grantee), 1);
this.hiddenData.splice(this.hiddenData.indexOf(grantee.id), 1);
}
//The backend is outputting this on the DD
array:1 [▼
0 => "1,2"
]
I'm trying to make it out
array:2 [▼
0 => "1"
1 => "2"
]
Adding [] to the name of an input field is only useful when you have multiple input fields with this name. It does not convert the value of a single field to an array.
So you can just remove the [] from the name and do a simple explode on the string to make it an array.
dd(explode(',', $request->grantedUsers));

How to exclude fields from SimpleForm

I know <SimpleForm> is using redux-form.
I want to exclude specific fields from being sent when I submit the form.
When I edit my entity "User" the RestClient send a GET_ONE request and my API response this:
{
name: "Lior",
age: "100",
type: "Manager",
}
The <SimpleForm> is like this:
<SimpleForm>
<TextInput source="name"/>
<TextInput source="age"/>
</SimpleForm>
When I send the form, the fields I see in the request are: name, age and type even when there is no "input" or "field" for type.
How can I avoid from "type" to be sent?
The API has to return it, I need it for <Show> and more..
I don't to hard coded my RestClient just to remove the "type" because it is
not happening just in "User" model but in many other models.
I don't want to "usset" it on the API controller side.
Thanks!
There's no react-admin way to doing this. I think a restClient middleware is the way to go, but you don't want that. What you can do is to create a HOC using mapProps of recompose and wrap SimpleForm with it. Something like (untested code):
const withLimitedProps = properties => mapProps(({save,...props}) => ({...props,save: (record,redirect) => save(properties.reduce((acc,property)=>{
acc[property]=record[property]
},{})});
const UserEditForm = withLimitedProps(['name','age'])(SimpleForm)
The save prop is proxied, and the record that's submitted is reduced. You can always add more functionality, like selecting the current fields from the redux-form state and reducing on them only. This would give the behaviour that you want.
You can customize your restClient to only send a subset of fields when calling UPDATE:
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'PUT';
const { name, age } = params.data; // type is ignored
options.body = JSON.stringify({ name, age });

How to work with app-localstorage-document in Polymer

I am trying to figure out how to set and retrieve a value in the app-localstorage-document. I worked before with the iron-meta element and did it like so:
<iron-meta id="meta" key="id" value="{{meta}}"></iron-meta>
Polymer({
is: 'login-form',
properties: {
meta: {
type: String,
value: ''
},
},
getValue: function() {
this.meta = '100'
var savedValue = this.$.meta.byKey('id');
console.log(savedValue);
}
});
But when I try something similar with the app-localstorage-document it just returns: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
I cant find any example on how to work with this element. Maybe someone can help me out here.
<app-localstorage-document id="meta" key="id" data="{{meta}}" storage="window.localStorage"></app-localstorage-document>
Polymer({
is: 'login-form',
properties: {
meta: {
type: String,
value: ''
},
},
getValue: function() {
this.$.meta.setStoredValue('id', '50');
var savedValue = this.$.meta.getStoredValue('id');
console.log(savedValue);
}
});
I am still studying this element myself. The documentation is not all that direct. This what I understand so far.
The issue is more about changing the way you think about accessing the storage data. The app-localstorage-document element is handling it for you.
<app-localstorage-document id="meta" key="id" data="{{meta}}" storage="window.localStorage"></app-localstorage-document>
The attribute "data" is synced with the storage key of "id". Any time "id" is updated, the variable assigned to "data" is updated. This means in this changes to the key "id" will bubble up into the variable "meta".
If you need to access information in storage, it should be accessible in the "meta" variable.
this.meta.name or {{meta.name}}
this.meta.id or {{meta.id}}
This would imply that the variable assigned to "data" should be of type Object.
meta:{
type:Object,
value:{},
notify:true
}
As a result, if you are using this element, there is no reason to directly access local storage. That is what this element is for.
The basic idea is to synchronize in-memory data to localStorage.
app-localstorage-document stores the 'data' in localStorage or sessionStorage. Any change in data flows back to storage. In your case, you just need to set the {{meta}} object with desired values, and app-localstorage-document will ensure that it is stored in local storage.
As you can always work with in-memory data, you might not read the data from localStorage in the same element. However, to read the stored data in other elements, you could use iron-localstorage or even directly read from localStorage with the key.

Resources