Join egghead, unlock knowledge.

Want more egghead?

This lesson is for members. Join us? Get access to all 3,000+ tutorials + a community with expert developers around the world.

Unlock This Lesson

Already subscribed? Sign In


    Validate Errors onInput in an Elm Form

    Enrico BuonannoEnrico Buonanno

    Validating input as soon as the user starts typing is considered a bad idea. On the other hand, clearing an error as soon as the user has fixed her input improves the user experience. So, sometimes you want to perform validation on input.

    In this lesson we'll ensure the error message is only displayed after submit, and only displayed on input if there was a prior error.



    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson


    Instructor: 00:00 The advantage of validating a form or submit is that you can ensure that the data is valid before you send it to the server. On the other hand, the user experience is not always optimal.

    00:10 Imagine the user enters some data like this. Now he gets a validation message and he says, "Oh, I need to fix this," I type two and he's a bit fiddly, so again he goes to submit. Oh, and again it's invalid. Notice that as we type here, the validation is always clear so the user never really knows whether the data is valid or invalid as he types.

    00:42 Somehow, what would be nice is that, once have this error, the error stays until I've actually fixed my input. I notice how the current behavior is determined by the fact that as the user types, we get this input email message, and this creates a new field that would be in the not validated state.

    01:01 What if we said create a new field and then validate it? We've defined it somewhere here, so we'll just need to move this to finishing up to top level. Let's try now, and I'll notice that, as soon as I start typing, I get a validation error.

    01:26 This is considered very bad user experience. You're giving a user some negative feedback before he even gets a chance to complete his input. In fact, what we need is completely different validation logic on submit and on input.

    01:41 On submit, we always want to validate no matter what. On input, we only want to validate if the field has somehow been committed before. Let me find a way to express this in my code. Let me write the new type, we shall call event, and this can be on submit or on change, so when the row value changes.

    02:04 On change, we have a payload, let's call this row. This is the new value coming from the UI. Now, this function validates. Let me just duplicate it. I'm going to rename this validate always, because this always performs validation.

    02:21 Let me have a more generic validate function that additionally takes an event. Then, we can switch on the type of event. On submit, we do the same logic as before, so we always validate, given validate and the field.

    02:51 What about on change? With the value, let's call this new value. Let's say validate if validated, with the validated function, the field that has the new value and the current validity. The signature would be the same as this, but the name is validate if validated.

    03:21 Here, we can return a field with the new value, value. For the new validity, let's switch on the existing validity. If it's not validated, then we want to leave it as not validated, and otherwise, we want to perform validation. That's the idea, let me just fix a couple of errors. Here I need parentheses, and this yields a result. Let me pass this to the validity.

    03:52 Here, I forgot to put the row type variable. Now, I can refract to the code in my Elm file to use this new signature for the validate function.

    04:26 Let's see how this changes, let's say I've a typo here and submit. When I go back, notice that as a type the application keeps checking for the validity, and error goes a way as soon as my input is fixed. Now, let me do the same refactoring for the other two fields.

    04:59 Notice that in confirm password validation, we need this extra parameter that's the pass out field. Let me add that here. Here, I need to call it with password. Next, let me change the update function.

    05:51 Let's test the application. Let's see, if I change this input, it's still being invalidated at every key stroke. The user is getting some feedback for when the errors are fixed. Notice however that for the two related fields, we're asked to do any validation only when the form is submitted.

    06:25 Let's see how we could address this. Essentially, when the user changes his password, we should again check that the two passwords match. Let me copy this validation here and perform this on input password as well. Now this is not the model.password, but rather the newly validated password, essentially this. Let me put this into a variable.

    06:48 Notice that the event is not on change because the confirm password field hasn't really changed. What happened is that a related field changed, so you could call this on related change. Let me now create it for this new type of event.

    07:17 I'll use validate if validated, this would prevent any annoying errors when the user is first filling out the form. The only difference is that, we don't have a new value. Let's see how this changes. Let me enter Hello1 and Hello2.

    07:47 Here the passwords don't match. Now, let me fix this to the Hello2, and now the error went away. If I enter Hello22, then the password don't match. We have validation as the user types.

    08:05 Notice that we still have a no annoying errors while the user is first filling out his form. Hello22 and Hello2, these don't match, but the error won't show until you click submit. Only afterwards, when you might need a bit of a hand to correct your input does the validation occur.