Series: Form Validations with ember-validations

Displaying Validation Errors

Published on Aug 14, 2015

Validation errors are far more useful if you can show them to your users.

In this screencast we look at two different strategies- flash messages and inline messages.


Links

Code

Display errors in flash messages:

actions: {
  save(){
      //...
      this.validate().then(()=>{
        model.save().then(()=>{
          this.transitionToRoute('post.show', model)
        })
      }).catch(()=>{
        var errorHashes = this.get('errors.model')
        var errorKeys = Object.keys(errorHashes)
        this.get('flashMessages').clearMessages()
        errorKeys.forEach((key)=>{
          errorHashes[key].forEach((error)=>{
            this.get("flashMessages").danger(`${key} ${error}`, {sticky: true})
          })
        })
        console.log(this.get("errors"), errorKeys)
      })
  }
}

You can also display errors inline. Here's a display-errors component you can use:

{{#if showErrors}}
  {{#each errors as |error|}}
    <p style="color: red;">{{error}}</p>
  {{/each}}
{{/if}}

And here is it being used in a template:

<p>Title: {{input value=model.title}}</p>
{{display-errors errors=errors.model.title showErrors=showErrors}}

<p>Length (in seconds): {{input value=model.seconds}}</p>
{{display-errors errors=errors.model.seconds showErrors=showErrors}}

The showErrors attribute usually starts off false, but then is turned to true when validation fails.

Transcript

In the last episode, we used the ember-validations library in order to show errors on our forms. However, we didn’t actually show errors on our forms yet. We just caught the errors and showed them in a console.log. In this episode, we’re going to be talking about how to display those validation errors. We’re going to be doing this in two ways. The first is through flash messages, and the second is through inline error messages.

So flash messages, in Episode 57 we learned how to use ember-cli-flash to show those, and we already have flashMessages in the application template. What we need to do is in our controller, we take our errors hash and we turn that into a series of flash messages that can show to the user. So to jog your memory, this is how flash messages work. First, you call to get flashMessages, and then you add them by calling something like warning or success, or in this case, danger, and then you send it a message. Now when we have an error, it’ll display a flash message.

However we’re going to want something more specific than that. We’re going to want to get it from the errors. The errors hash if you remember it from last time is a series of nested hashes, so it has model. The model has several different properties, seconds and title in this case. And then it has errors on each one where there are errors. In this case there are two errors on title and none on seconds.

So first we’ll get the various errorHashes, and we’ll get that from the errors hash going down to the model, then we’ll pull the various keys from it. In this case it’ll be title and seconds. Then we’ll loop through those keys and use that to pull the value out of the errorHashes. Each value is an array of different messages, so we’ll loop through that. Then we’ll grab our flashMessages array and we’ll add something that says key and then the error, so it’ll say something like 'title is not long enough'. Then we can removethis old flash message.

Let’s go ahead and look this in action. So we remove this 'Title', we’ll make this not a number, and it’s giving us these errors. But they go away really quickly, so let’s go ahead and make them sticky, and since they’re sticky we’ll need to remove them every time. So we’ll run this again, it gives us these errors, and they can stay there. The user can make them go away by clicking on them.

So this works and it’s fairly easy, and you could theoretically create a method called like sendErrorsToFlash and have that run wherever you want to have this type of action. It’s agnostic to what the errors actually are. However the user experience is not great. You see these errors and you have to go find them below, and in the case of seconds it looks like it’s called ‘Length’ even though it’s named ‘seconds’. So let’s try to find a way to put these in line.

So below each of the things where we have a validation, we’ll want some sort of component. We’ll call it display-errors. And then we’ll pass it in errors, and we’ll pass it in a boolean that says whether it will show the errors. So the errors in this case will be found on the errors hash, and then we’ll go into the model and then title, and then showErrors will be appropriately named. Notice the correspondence here. So we’ll separate this out, and the value of this input is model.title, and the errors are errors.model.title.

So what would this display.errors component look like? We would have an if statement saying okay, we’re only going to show these if the showErrors boolean is true. Then we’re going to loop through the errors and show all the errors in red. Then we’ll go ahead and create another display-errors component for the other property that has a validation. And then notice that this is in the edit-fields component so we’ll have to pass in the errors hash and the showErrors boolean to that component. So we’re back in the edit controller, and let’s start off by having showErrors equal to true, and we’ll see how that affects it. So we can start deleting this and when it gets below 5, it’ll show that error, and when there’s nothing it’ll say can’t be blank.

This is pretty good, so I’d say this is good for edit, but why did we want to have that showErrors boolean? So let’s go to our posts/new/template, and when we’re calling the edit-fields, we’ll put in showErrors and errors, and then we’ll go ahead here in the controller, set showErrors to true. Let’s see what happens there. This is basically repeating the work we did for the edit controller. So we start off with all the errors showing, and that’s not great. So in our new posts controller, we’ll set showErrors to false automatically. And then once saving has failed, then we’ll set showErrors to true. When we go to our page, it doesn’t show any errors until we hit save, and that’s just the behavior we want.

So in this episode, we saw two different ways to show the error messages to the user. One was using flash messages and the other was to show them inline. Tune in next week as we talk more about validations, how to do more advanced validations than just length and presence. I’ll see you then.

Form Validations with ember-validations

Subscribe to our mailing list