{"id":1923,"date":"2016-06-17T14:20:14","date_gmt":"2016-06-17T13:20:14","guid":{"rendered":"http:\/\/www.jurecuhalev.com\/blog\/?p=1923"},"modified":"2016-06-17T14:20:14","modified_gmt":"2016-06-17T13:20:14","slug":"ember-server-side-form-validation-with-mirage","status":"publish","type":"post","link":"https:\/\/www.jurecuhalev.com\/blog\/ember-server-side-form-validation-with-mirage\/","title":{"rendered":"Ember Server Side Form validation with Mirage"},"content":{"rendered":"<p>In this\u00a0Ember.js example, I&#8217;ll show\u00a0how to get ember-cli-mirage to return correct JSON-API response, so that\u00a0Ember Data correctly processes Error message and makes it\u00a0accessible inside the template.<\/p>\n<p>This code was tested on Ember 2.6.0.<\/p>\n<p>We have the following\u00a0registration model:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">import Model from 'ember-data\/model';\r\nimport attr from 'ember-data\/attr';\r\n\r\nexport default Model.extend({\r\n  firstname: attr('string'),\r\n  lastname: attr('string'),\r\n});<\/pre>\n<p>There are\u00a0three main\u00a0elements\u00a0that make this work: <strong>Controller<\/strong> that saves the data, <strong>Template<\/strong> that renders\u00a0form and errors, and <strong>Mirage<\/strong> that mocks the response.<\/p>\n<p>Controller&#8217;s save action is very basic,\u00a0it calls save on the model and\u00a0catches any errors:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">import Ember from 'ember';\r\n\r\nexport default Ember.Controller.extend({\r\n  actions: {\r\n    save() {\r\n      this.get('model').save().then((registration) =&gt; {\r\n        \/\/ it's a mock, we don't do anything\r\n      }).catch((adapterError) =&gt; {\r\n        \/\/ we just need to catch error\r\n      });\r\n    }\r\n  }\r\n});\r\n<\/pre>\n<p>Template displays form and any connected errors:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;form&gt;\r\n  &lt;p&gt;\r\n    &lt;label&gt;First name: {{input value=model.firstname}}&lt;\/label&gt;\r\n    {{#each model.errors.firstname as |error|}}\r\n      &lt;span class=&quot;errors&quot;&gt;{{error.message}}&lt;\/span&gt;\r\n    {{\/each}}\r\n  &lt;\/p&gt;\r\n  &lt;p&gt;\r\n    &lt;label&gt;Last name:\r\n      {{input value=model.lastname}}\r\n    &lt;\/label&gt;\r\n    {{#each model.errors.lastname as |error|}}\r\n      &lt;span class=&quot;errors&quot;&gt;{{error.message}}&lt;\/span&gt;\r\n    {{\/each}}\r\n  &lt;\/p&gt;\r\n  &lt;button {{action 'save'}}&gt;Save&lt;\/button&gt;\r\n&lt;\/form&gt;\r\n<\/pre>\n<p>Now we only need to setup Ember Mirage. We emulate two different states. If firstname is &#8216;John&#8217;, we let request come through, and in all other cases we display error.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nimport Response from 'ember-cli-mirage\/response';\r\n\r\nexport default function() {\r\n\r\n  this.namespace = '\/api';\r\n\r\n  this.post('registrations', function(schema, request) {\r\n   let attrs = JSON.parse(request.requestBody).data.attributes;\r\n\r\n   if ( attrs.firstname === 'John') {\r\n     return {\r\n       'id': 1,\r\n       'firstname': 'John',\r\n       'lastname': attrs.lastname\r\n     }\r\n   } else {\r\n     return new Response(422, {}, {\r\n        &quot;errors&quot;: &#x5B;\r\n          {\r\n            &quot;source&quot;: { &quot;pointer&quot;: &quot;\/data\/attributes\/firstname&quot;},\r\n            &quot;detail&quot;: &quot;Please enter John as name&quot;\r\n          }\r\n        ]}\r\n     );\r\n   }\r\n  });\r\n}\r\n<\/pre>\n<p>In the above example, it&#8217;s important that we return error code 422 (Unprocessable Entity), otherwise it will not be processed by  JSONAPIAdapter as error.<\/p>\n<h2>Example repository<\/h2>\n<p>To make easier to see a complete and working example, I&#8217;ve also published a repository with complete code:<br \/>\n<a href=\"https:\/\/github.com\/ember-examples\/server-side-validation-mirage\">https:\/\/github.com\/ember-examples\/server-side-validation-mirage<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this\u00a0Ember.js example, I&#8217;ll show\u00a0how to get ember-cli-mirage to return correct JSON-API response, so that\u00a0Ember Data correctly processes Error message and makes it\u00a0accessible inside the template. This code was tested on Ember 2.6.0. We have the following\u00a0registration model: import Model from &#8217;ember-data\/model&#8217;; import attr from &#8217;ember-data\/attr&#8217;; export default Model.extend({ firstname: attr(&#8216;string&#8217;), lastname: attr(&#8216;string&#8217;), }); There [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[925],"tags":[],"class_list":["post-1923","post","type-post","status-publish","format-standard","hentry","category-ember-js"],"acf":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/1923","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/comments?post=1923"}],"version-history":[{"count":6,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/1923\/revisions"}],"predecessor-version":[{"id":1929,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/1923\/revisions\/1929"}],"wp:attachment":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/media?parent=1923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/categories?post=1923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/tags?post=1923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}