So now that we have this basic form set up with our own input component,
let's adjust this to also be able to react to user input and to get the user input.
So for that my input component, each element of course should receive onChange listener,
so let's add one to each of the elements we are creating here.
So I'll go through all of them and I'll just use IDE option where I can place multiple cursors, add
onChange to all of them
and of course I don't want to handle the change in this component,
I expect to get a method reference from outside which then takes care about this.
So here I'll simply add props and I'll name the property changed and you can of course choose any prop
name you want.
Now changed is the name I chose
so in contact data, I now actually need to implement the method which reacts to the changed properties,
so where I can fire up onChanged, which I can pass to to change prop
which then in the end will be attached to the onChange event.
So for that,
I'll create a new method in my contact data component, I'll name it inputChangedHandler, there I expect
to get an event object as it will automatically be passed to me by react
if this method is attached to an event listener which it of course is.
So the inputChangedHandler is what I passed to the changed prop, this inputChangedHandler,
no parentheses as always.
And now here, I want to first of all log the event target value to see any output and see if it's generally
working.
Let me type something into your name,
I do see it here on the right, also for the zipcode and also for the dropdown
so we do receive that value,
we connected it successfully.
But of course, we can see the values in our inputs because what's missing is the other part of two
way binding.
We're not using this data here when the input changes to update the value of our elements
and of course, we have that value key for each input element which we bind to it,
so this is currently the key which determines the value which is shown on the screen.
So we need to update the value for a given input upon user changes, for that of course we need more
information than just the event which gives us access to the event target value,
we also receive or need a second argument which is the input identifier so that we can reach out to
our state, get the right element here, the right object and adjust its value.
So to do that, I'll go to my contact data component and the method I passed to changed, the reference here
should be a referenced to an anonymous function
so that I can now pass arguments to the inputChangedHandler method call. In this anonymous function,
here we now get this event object which is created by react automatically
and I want to pass this on but I also now want to pass my identifier, which is form element ID, that
is this ID which is just a key from our object
and that's exactly what I need.
These keys here in our state object,
these are the identifiers of the inputs and exactly the objects I need to adjust it.
Now of course, I can use that information to update the value,
the problem just is I of course can't access this.state.orderForm identifier and update the value,
this is not how we mutate the state.
Instead we have to mutate it,
well immutably and we do this with set state and for that, what I'll do is I'll first of all create my copy
my form data,
so from the state here, my order form, I'll create,
copy it.
So I'll name this updatedOrderForm and for that here, I will now create a javascript object where I copy
this.state.orderForm.
However this does not create a deep clone, so I copy that object and I distribute all the properties,
I get a new object but since these objects, I have more nested objects, these would not be cloned
deeply
but there, I will again just copy the pointer to them and hence if I change something there, I will
still mutate the original state
unfortunately because the object in my copied object and the object in the state would still be equal.
So we need to clone this deeply,
how do we do that?
Well in the end I only care about the value here
so I only need to make sure that this object here is also cloned and I don't point to the same object
anymore.
I can achieve this in my inputChangedHandler by not just distributing the properties of order form
which would be name, email and so on but that
I also copy the properties inside my selected order form element deeply. For this,
I'll take the updatedOrderForm which is a clone of the original one and not referring to the original
one anymore and there I'll now access
my input identifier
so this is a value like email, like
delivery method.
Now I get access to this object which we haven't cloned already
so now I need to clone that object and I'll store the new constant updatedFormElement, maybe.
In here again, I'll create a new object and used to spread operator here
to create a clone. Now I can safely change the value of the updatedFormElement because it is again
a clone.
Only if I were to change the element config, that would still be an object which I haven't cloned which
points to the original one but I'm not doing that here
if you are doing that, you need to also clone that deeply with the spread operator.
So I will reach out to updatedFormElement value and set this equal to event target value
and now, I can take my updatedOrderForm, so this which is my clone original form and there, I can now
again access the input identifier and set it equal to the updatedFormElement.
Now with this, I can call this.setState and set order form to updated order form.
Now let's see if this works, if I save this and I go back to my application and type something
into your name like Chris, you see this works, let's try it for all these inputs there.
Let's also try the dropdown,
this is all updated so two way binding is now working.
Now we successfully set this up in a very generic way which is great.
Now let's turn our heads towards form submission then.