Ember cp-validations - belongsTo validation


I didn’t find the answer in the examples provided in ember-cp-validation dummy app as well in their presentation.

I have to validate a language in the following model:

# models/shop-language.js

import DS from 'ember-data';
import { validator, buildValidations } from 'ember-cp-validations';

const Validations = buildValidations({
  language: {
    description: 'Language',
    validators: [validator('ds-error'), validator('presence', true)]

  shop: {
    description: 'Shop',
    validators: [validator('ds-error'), validator('presence', true)]

export default DS.Model.extend(Validations, {
  shop: DS.belongsTo('shop', { async: true }),
  language: DS.belongsTo('language', { async: true }),
  modifiedBy:  DS.attr('string')

On which property should I use v-getin the template if I load 2 models from my route:


model() {
    return RSVP.hash({
      shopLanguages: this.store.query('shop-language', { shop_id: this.get('currentShop.shop').get('id')}),
      languages: this.store.findAll('language')

Here is the template:

{{#each model.shopLanguages as |shopLang|}}
        <li class="list-group-item">
          <button type="button" class="btn btn-danger btn-sm" disabled={{isDeleteButtonDisabled}} {{action "deleteLanguage" shopLang}}>
            <span class="oi oi-trash"></span>

  <form {{action "saveLanguage" aLanguage on="submit"}} class="form-inline">

          {{#if showLanguageError}}
            <div class="alert alert-danger">
              {{v-get aLanguage 'id' 'message'}}

          <div class="col-sm-2">
              noMatchesMessage=(t 'components.language.labels.not.found')
              onchange=(action (mut aLanguage))
              focus-out=(action (mut showLanguageError) true)
              as |language|

<div class="form-check sm-2">
            <button type="button" type="submit" class="btn btn-success btn-sm">
              <span class="oi oi-plus"></span>
              {{t 'buttons.add'}}

Here is how I tried to save a newly added language in the route:

# routes/shop-languages.js

actions: {
  async saveLanguage(aLanguage) {
  try {
        await shopLanguage.save();
        controller.set('aLanguage', '');
      } catch(response) {
        let error = response.errors[0];
        console.log('+++++ in CATCH block error: ' + error);
        if (error.status !== "422") {
          throw response;

It prints the error to the console but displays nothing in the template … :frowning: The response I get from Rails backend if language is not selected:

{"message":"Couldn't find Language"}

Should parse in some way this message to be able to display it ? And the error object is as follows:

{status: "404", title: "The backend responded with an error", detail: "[object Object]"}

Thank you.


A few things stand out as possibly wrong:

  1. showLanguageError is not set to a truthy value so the error message is not going to be rendered.
  2. You have {{v-get aLanguage 'id' 'message'}} in the template but the validation is not set up on the id property of aLanguage.
  3. I suppose aLanguage is a ShopLanguage but the code snippets don’t tell us that.



Even if I remove ifcondition (this would enable displaying errors on the form display), nothing happens. That’s why I wonder what is the syntax to use when calling v-get:

# extact from RARWE book, page 291.

{{v-get model 'email' 'message'}}

All the provided use cases suppose to have ONE model defined in the route (like creating a User or a Post, for example).

aLanguage is an instance of Language model to be selected from the drop-down list (value to submit -> language.id, displayed value -> language.tag.

As I described earlier, the relations are defined as follows between Shop, ShopLanguage and Language models:

Shop: hasMany ShopLanguages
ShopLanguage: belongsTo Shop
ShopLanguage: belongsTo Language

You can see how it looks in the below screenshot.


It doesn’t matter what your model is in the corresponding route. What matters is which object you added the validations onto that you’re checking.

v-get is just a nifty helper to prevent you from having to write lengthy expressions (see [the relevant page from the docs here).

So {{v-get model 'email' 'message'}} desugars to {{model.validations.attrs.email.message}}. In your case, {{v-get aLanguage 'id' 'message'}} is equivalent to {{model.validations.attrs.id.message}} which might not be what you want – unless you added a validation to the id property.