accessing formsection children form values in parent (redux-form) - redux-form

ParentForm.js
<FormSection name="ChildRequestForm">
<ChildForm />
</FormSection>
on form submission in ParentForm, it should get values from ChildForm component, this works fine.
But once the ChildForm component has a reduxForm connected
ex:
ChildForm = reduxForm({
form: 'ChildRequestForm'
})(ChildForm);
then the parent form will no longer able to retrieve values of the child form on submit.
I had to wrap the child component with reduxForm as the form requires to dispatch 'change' function and requires access to formvalueSelector
Sandbox Link
https://codesandbox.io/s/jj1mk114n5
any help?

Childform should have the same name as parent form (in your example it is 'foo'). So to make the child form name dynamic, pass a formname prop to your child component and make use of it using mapstatetoprops ownprops.
By this way, you can reuse the child component with parent formname, whenever it is needed.
refer to dis
How do you pass in a dynamic form name in redux form?

Related

How to destroy livewire component on click?

I've created a livewire component with some input fields, added a for loop to the parent component with the child component inside.
#for($i = 0; $i < $count; $i++)
#livewire('dashboard.profile.garage-service-list-item', ['garage' => $garage], key($i))
#endfor
Each child component has a delete button. How can the method for this button look like?
Two ways spring to mind. One being that you display an empty view if the item gets deleted, or you fire an event to refresh all the components that are rendered within that loop.
1: Refreshing the parent
This assumes that the parent component is a Livewire component.
In your parent, you can listen for an event to refresh itself. Simply declare a listener in your parent component (the component that has your #for loop), by adding the following.
protected $listeners = ['refreshParentComponent' => '$refresh'];
refreshParentComponent is the name of the event, you could rename it to something more suitable (that name is probably not a good name), and $refresh is the action -- and in Livewire, the $refresh action is a magical action that simply refreshes the component in its entirety, basically re-rendering it. This would mean that you will get a fresh set of data after deleting the item, and render it all with that data.
To make the event trigger, in your Profile\GarageServiceListItem class, where you delete the item, you can fire, or emit, that particular event - and you can emit it upwards. You can do that by calling the emitUp method.
$this->emitUp('refreshParentComponent');
2: Rendering an empty HTML block
You can add a boolean property to your Livewire-component, for example public $show = true;. Then in the base of your garage-service-list-item view, you start by checking that property.
<div>
#if ($show)
<!-- The rest of your component here -->
#endif
</div>
Then in the method where you delete the component, simply set $this->show = false; and you're done! The component will render a empty <div> block.
Livewire events
Livewire properties

Async validate single redux form field, but not on submit

Question
How can one build a async validation on a single form field that also can trigger filed level errors, but without using a asyncValidation that also triggers onSubmit?
Background to question
I have a Redux form where the user can choose to:
a) Input adress details by hand
b) Fill in their social security number and fetch all details from a API and get the redux form fields prefilled (wohoo, time saved!)
c) Being 100% anonymous by checking a checkbox which removed all personal details fields.
Given this kind of setup a asyncValidator that triggers onSubmit and onBlur seems tricky, i don't want them to trigger more than once if a get the desired details and the form get pre-filled. But if user submits a invalid social security number I want to trigger a field error.
if you just want to validate a single field, you can pass a prop validate
with an array of validation functions, that will return false if its valid, and a string error if invalid based on your logic. and will prevent submission, or will show an error on submittion.
const required = (value) => (value ? false : 'Required')
const isSSN = (value) => (willBeTrueIfSSN ? false : 'Invalid SSN')
<Field name="ssn" validate={[isSSN, required]} {...rest} />
some good examples in the redux-form docs:
https://redux-form.com/7.2.3/examples/fieldlevelvalidation/

Vuejs how to pass component data from caller

My main page renders a list of data coming from controller with foreach
#foreach ($sales as $sale)
<button id="{{$sale->id}}" #click="editClicked({{$sale}})">
#endforeach
I have an edit component placed on the page like this, I display it modally via showEditModal conditional
<edit v-if="showEditModal" #hide="showEditModal=false"></edit>
The component in brief is declared in Edit.vue:
<template name="edit">
...
</template>
This is simply a standard form with input fields, bound via v-model to the sale.
Essentially it is an update form, I intend to load the data from the main page into each input field to be edited.
My app.js simply sets showEditModal = true, in order to display the edit form on top of the main page.
Basically i don't want to have to call controller via GET method on loading the modal since i already have the data in the main page as $sale object, so im just wondering how do I pass in the $sale to the Edit.vue component ?
I thought that in the <edit> component usage, it would need to bind the sale object, however I'm unsure how that would work since it comes from the foreach loop.
I do, also have the data in the app.js method as passed in via #click="editClicked({{$sale}})", but again, i'm unsure how to use that to pass through ?
You're right, you would want to pass the current sale item as a property to the edit modal. What I would do is add a data property to your main Vue called selectedSale.
data:{
selectedSale: null
}
Then in your editClicked method, set selectedSale
methods:{
editClicked(sale){
this.selectedSale = sale
...
}
}
Finally, pass it as a property.
<edit :sale="selectedSale" v-if="showEditModal" #hide="showEditModal=false"></edit>

Web2py: how to cancel a form submission within a LOADed component

If I have a web2py view (say tmp.load), I can force the form not to submit by returning false from the on submit handler.
<form onsubmit="return false;"><input type="text"><input type="submit" /></form>
That works when I view it directly: this form never submits. But if I load this view using
{{=LOAD('tmp.load', ajax=True)}}
Then the form submits, even though I was expecting it not to. So how do I write a LOAD component that contains a form which can be programmed not to submit if certain js conditions are met?
web2py.js automatically sets up event handlers for forms in components in order to submit them via Ajax. One possible approach is to intercept web2py's Ajax submission by setting up an ajax:beforeSend event handler. For example, in the view of the component (i.e., tmp.load), something like:
<script>
$(document).on('ajax:beforeSend', function(e, xhr, settings) {
if (settings.type === 'POST') {
if(abortAjaxSubmission) {
xhr.abort();
$.web2py.enableFormElements($('form#myform'));
}
}
});
</script>
In the above, abortAjaxSubmission represents the condition where you want to stop the submission. The selector form#myform represents the form in the component (you need to re-enable the form elements because web2py disables them upon submission but only re-enables them upon completion of the Ajax request, which won't happen if you abort).

How do I auto fill field values in a section of a form that is loaded via ajax in Laravel 4?

I have a section of a form that dynamically loads different sets of fields based on the user's selection in a control. I'm using a javascript event handler to detect when the selection changes, and using AJAX (with HTML payload) to pull in the proper set of fields.
I would like to be able to use Laravel's Form::getValueAttribute() method to automatically fill in the form fields' values in both the static and dynamic form parts. However, the partial view that is loaded by my AJAX call does not have the same instance of the Form class as the view with my main Form, so I can't simply call getValueAttribute() in the partial.
My thought is to make the AJAX call a POST, and serialize the necessary data (a subset of Input::old() or the model data depending whether the page is loaded as the result of validation errors, or an UPDATE request) to send along with the POST so that the HTML fragment I get back has the values set properly.
Is this the best way to get what I want? If so, does Laravel have any tools to help with the serialization of form data? If not, what might be a better approach?
I've found an approach I like better. When the view is loaded normally I use AJAX as usual to load the partial. But when the view is loaded for a validation post-back or for editing, I use Laravel's Views' nest method to nest the partial view containing the proper fields directly into the response. The partial then has access to all the Input and error data I need. The user is still able to change the field set as usual but I put up a confirm prompt for them if they have already set some values in a field set they previously selected. If they decide to proceed anyway, the field set is cleared and a new field set is brought in via AJAX as usual.
My code looks something like this:
Controller:
public function newThing() {
if ( Request::session()->has('errors') ) {
// this is a validation post-back
return View::make('thing')
->nest('fields', 'fields_partial');
} else {
// just a normal unfilled form
return View::make('thing');
}
}
public function editThing() {
return View::make('thing')
->nest('fields', 'fields_partial');
}
View: thing.blade.php (just a snip of it)
...
<form>
...
<select id="picker">...</select>
<div class="sub-fields">
{{ isset($fields) ? $fields : '' }}
</div>
...
</form>
...
<script>
$('#picker').change(function() {
// if any .sub-fields inputs have been changed, get confirmation from the user
// if user confirms, do ajax stuff to replace .sub-fields contents with new field set
// otherwise cancel the change
});
</script>

Resources