{"id":444,"date":"2016-11-28T22:01:08","date_gmt":"2016-11-28T22:01:08","guid":{"rendered":"http:\/\/www.corrspt.com\/blog\/?p=444"},"modified":"2016-11-28T22:01:08","modified_gmt":"2016-11-28T22:01:08","slug":"ember-conventions-over-conventions","status":"publish","type":"post","link":"http:\/\/www.corrspt.com\/blog\/2016\/11\/28\/ember-conventions-over-conventions\/","title":{"rendered":"Ember &#8211; Conventions over Conventions"},"content":{"rendered":"<p>Today I want to talk about conventions and share something I&#8217;ve been doing as I&#8217;m working in my app that uses <a href=\"http:\/\/emberjs.com\">EmberJS<\/a>\u00a0for the front-end.<\/p>\n<p>Warning: This post\u00a0does assume a certain degree of familiarity with\u00a0ember\/ember-cli and I assume that you have all things installed necessary to run\/build an ember app. There&#8217;s a full repository on github with the <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/\">complete project<\/a>, which I&#8217;ll reference from here.<\/p>\n<p>We&#8217;re going to create a very simple app with\u00a0components that have <a href=\"https:\/\/en.wikipedia.org\/wiki\/Internationalization_and_localization\">i18n<\/a>, real-time validation, use DDAU (data down, actions up) and some baked-in conventions to make things more &#8220;robust&#8221;. It will look something like this:<\/p>\n<div id=\"attachment_445\" style=\"width: 810px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-445\" class=\"size-full wp-image-445\" src=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result.jpg\" alt=\"Components with validation and i18n\" width=\"800\" height=\"138\" srcset=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result.jpg 800w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result-300x52.jpg 300w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result-768x132.jpg 768w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/final-result-500x86.jpg 500w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-445\" class=\"wp-caption-text\">Components with validation and i18n<\/p><\/div>\n<p>The first thing is to create a new project using ember-cli (at the time of writing\u00a0EmberJS is on version 2.9.1) on the terminal:<\/p>\n<blockquote><p>ember new\u00a0<span class=\"s1\">blog-post-ember-conventions-steps<\/span><\/p><\/blockquote>\n<p>Then, since we&#8217;re going to use i18n, I recommend the excellent <a href=\"https:\/\/github.com\/jamesarosen\/ember-i18n\">ember-i18n addon<\/a>\u00a0and to make things look good we&#8217;ll use <a href=\"https:\/\/github.com\/kaliber5\/ember-bootstrap\">ember-bootstrap<\/a> and to make validations we&#8217;ll use <a href=\"https:\/\/github.com\/esbanarango\/ember-model-validator\">ember-model-validator<\/a>. Also, I like to use <a href=\"https:\/\/github.com\/jmurphyau\/ember-truth-helpers\">ember-truth-helpers<\/a>, so I&#8217;m going to install them for later. To install just do the following on the terminal (see this <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/c54f2e69df9aa10cc3f660af6df402e1b4bf119d\">commit for the results<\/a>):<\/p>\n<blockquote>\n<p class=\"p1\"><span class=\"s1\">ember install ember-i18n<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">ember install ember-model-validator<\/span><\/p>\n<p class=\"p1\">ember install ember-bootstrap<\/p>\n<p class=\"p1\">ember install ember-truth-helpers<\/p>\n<\/blockquote>\n<p class=\"p1\">To finish installing ember-i18n, we&#8217;ll need two locales (so that we can switch between them), so we just type this in terminal (to create the english and portuguese locales, see <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/982c3ebe132e8fc5207918d13473757af55d3de9\">this commit<\/a>):<\/p>\n<blockquote>\n<p class=\"p1\">ember generate locale en<\/p>\n<p class=\"p1\">ember generate locale pt<\/p>\n<\/blockquote>\n<p class=\"p1\">With the required addons out of the way it&#8217;s time to generate a new route so that we can work on something (<a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/2c2a54cde694fb20ed9e81021c08ffb99ad5f0f0\">see this commit<\/a>).<\/p>\n<blockquote>\n<p class=\"p1\">ember g route application<\/p>\n<p class=\"p1\">ember g controller application<\/p>\n<\/blockquote>\n<p class=\"p1\">And we&#8217;re going to need a model for this whole thing to work, so I&#8217;m going to create a person model:<\/p>\n<blockquote>\n<p class=\"p1\">ember g model person<\/p>\n<\/blockquote>\n<p class=\"p1\">We&#8217;re going to include a simple <strong>name<\/strong> and <strong>age<\/strong> attribute, so we get the <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/b558090bcd4548888362bc597b4ad88ac4d46099\">following definition<\/a>:<\/p>\n<pre>import DS from 'ember-data';\r\n\r\nconst {\r\n Model,\r\n attr\r\n} = DS;\r\n\r\nexport default Model.extend({\r\n name: attr('string'),\r\n age: attr('number')\r\n});<\/pre>\n<h1>Component with DDAU<\/h1>\n<p>For starters we&#8217;re going to create a component to handle text\/numeric values which adheres to Data Down Actions Up. In terminal type:<\/p>\n<blockquote><p>ember g component attribute-text<\/p><\/blockquote>\n<p>In our component template we&#8217;re going to use a standard bootstrap form definition (I&#8217;m omitting a way to bind the value on purpose):<\/p>\n<pre>&lt;div class=\"form-group\"&gt;\r\n &lt;label title=\"{{placeholder}}\" \r\n   class='control-label'\r\n   for='{{attribute}}'&gt;\r\n   {{label}}\r\n &lt;\/label&gt;\r\n &lt;input\r\n   value={{get model attribute}}\r\n   class='form-control'\r\n   placeholder={{placeholder}}\r\n   type='text'\r\n   id={{attribute}}\r\n &gt;\r\n&lt;\/div&gt;<\/pre>\n<p>To make things dynamic, the value of the input uses the <a href=\"http:\/\/emberjs.com\/api\/classes\/Ember.Templates.helpers.html#method_get\">get helper<\/a>\u00a0which allows me to get a dynamic property, in this case from the model (in the <strong>{{get model attribute}}<\/strong> line).<\/p>\n<p>If I now make my route return a new person instance (so that we have a model to work with)<\/p>\n<pre>routes\/application.js\r\nimport Ember from 'ember';\r\n\r\nexport default Ember.Route.extend({\r\n model() {\r\n   return this.store.createRecord('person');\r\n }\r\n});<\/pre>\n<p>And I update\u00a0my main application template to display two components like this:<\/p>\n<pre>&lt;div class=\"container\"&gt;\r\n &lt;h2 id=\"title\"&gt;Conventions, Conventions&lt;\/h2&gt;\r\n\r\n &lt;div class=\"row\"&gt;\r\n &lt;div class=\"col-sm-6\"&gt;\r\n {{attribute-text\r\n   model=model\r\n   attribute='name'\r\n   label='Name'\r\n   placeholder='Insert your name'\r\n }}\r\n &lt;\/div&gt;\r\n &lt;div class=\"col-sm-6\"&gt;\r\n {{attribute-text\r\n   model=model\r\n   attribute='age'\r\n   label='Age'\r\n   placeholder='Insert your age'\r\n }}\r\n &lt;\/div&gt;\r\n &lt;\/div&gt;\r\n\r\n {{outlet}}\r\n&lt;\/div&gt;\r\n\r\n\r\n<\/pre>\n<p>We&#8217;ll get a result like the following (<a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/aa38977b5d6df16d9d286d3baedc097f02d308d9\">see this commit<\/a> with the result of all changes):<\/p>\n<div id=\"attachment_447\" style=\"width: 810px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-447\" class=\"wp-image-447 size-full\" src=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display.jpg\" alt=\"initial-display\" width=\"800\" height=\"121\" srcset=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display.jpg 800w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display-300x45.jpg 300w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display-768x116.jpg 768w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/initial-display-500x76.jpg 500w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-447\" class=\"wp-caption-text\">Initial Display<\/p><\/div>\n<p>Now,\u00a0it&#8217;s a start, but I\u00a0said we wanted to used DDAU on our component, so we&#8217;re going to make just that, we&#8217;ll add an <em>oninput<\/em> handler.<\/p>\n<pre>value={{get model attribute}}\r\noninput={{action this.attrs.onUpdateValue value=\"target.value\"}}\r\nclass='form-control'<\/pre>\n<p>We&#8217;re calling this action &#8216;onUpdateValue&#8217;, so we need to update the\u00a0application template (and controller) to have these actions.<\/p>\n<pre>templates\/application.hbs\r\n...\r\nplaceholder='Insert your name'\r\nonUpdateValue=(action 'setName')\r\n....\r\nplaceholder='Insert your age'\r\nonUpdateValue=(action 'setAge')<\/pre>\n<p>And in the controller, things look like this:<\/p>\n<pre>import Ember from 'ember';\r\n\r\nconst {\r\n Controller,\r\n get\r\n} = Ember;\r\n\r\nexport default Controller.extend({\r\n\r\n actions: {\r\n   setName(name) {\r\n     let model = get(this, 'model');\r\n     model.set('name', name);\r\n   },\r\n\r\n   setAge(age) {\r\n     let model = get(this, 'model');\r\n     model.set('age', age);\r\n   }\r\n }\r\n});<\/pre>\n<p>Ok, so now we have a DDAU compatible component, which is nice (<a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/63e9d0773a17206f9781ba11f60fa766132070d9\">see this commit<\/a>).<\/p>\n<p>Now let&#8217;s make\u00a0things more interesting!<\/p>\n<h1>Conventions on i18n<\/h1>\n<p>Ideally if I need to show the same field of a given model, I would like to have the labels\/placeholders all centralized in a localization file, so I&#8217;m going to do the following and\u00a0put the following\u00a0in my locales\/en\/translations.js (and the equivalent in \/pt\/translations.js) and not have to type\u00a0them in the template\u00a0every time.<\/p>\n<pre>export default {\r\n 'model': {\r\n   'person': {\r\n     'name': {\r\n     'label': 'Name',\r\n     'help': 'This name will be used throughout the application to display your name',\r\n     'placeholder': 'Person\\'s complete name'\r\n    },\r\n  'age': {\r\n    'label': 'Age',\r\n    'help': 'This field is used to validate access to some parts of the app, must be 18 or older',\r\n    'placeholder': 'The age (in years)'\r\n    }\r\n  }\r\n }\r\n};<\/pre>\n<p>Now, to make this work I would have to the following transformation (and use the &#8220;t&#8221; helper from <a href=\"https:\/\/github.com\/jamesarosen\/ember-i18n\">ember-i18n<\/a>).\u00a0Check <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/17e65a762ef81e0ddd7805f2397543ec11a602de\">this commit for the changes<\/a>.<\/p>\n<pre>templates\/application.hbs\r\n...\r\n{{attribute-text\r\n   model=model\r\n   attribute='name'\r\n   label=(t 'model.person.name.label')\r\n   placeholder=(t 'model.person.name.placeholder')\r\n   onUpdateValue=(action 'setName')\r\n}}<\/pre>\n<p>I mean, it&#8217;s kind of verbose, having to pass all that <strong>model.modelName.attribute.xxx <\/strong>over and over again, so I&#8217;m going to <strong>leverage conventions<\/strong> here. I know that my strings\u00a0are in a translations file with the structure\u00a0being:<\/p>\n<pre>model: {\r\n  attribute: {\r\n    label: 'The Label',\r\n    placeholder: 'The Placeholder',\r\n    help: 'The Help text'\r\n  }\r\n}<\/pre>\n<p>Let&#8217;s update our component to have some additional properties:<\/p>\n<pre>import Ember from 'ember';\r\n\r\nconst {\r\n Component,\r\n inject: { service },\r\n computed,\r\n} = Ember;\r\n\r\nexport default Component.extend({\r\n i18n: service(),\r\n\r\n attribute: '',\r\n\r\n getTranslation(property) {\r\n   return this.get('i18n').t(`model.${this.get('modelName')}.${this.get('attribute')}.${property}`);\r\n },\r\n\r\n modelName: computed.alias('model.constructor.modelName'),\r\n\r\n helpText: computed('i18n.locale', function() {\r\n   return this.getTranslation('help').toString();\r\n }),\r\n\r\n label: computed('i18n.locale', function() {\r\n   return this.getTranslation('label').toString();\r\n }),\r\n\r\n hasHelp: computed('helpText', function() {\r\n   return this.get('helpText').length &gt; 0;\r\n }),\r\n\r\n placeholder: computed('i18n.locale', function() {\r\n   return this.getTranslation('placeholder').toString();\r\n })\r\n\r\n});<\/pre>\n<p>We are going to leverage the fact that each DS.Model instance knows the model name (through <strong>constuctor.modelName<\/strong>) and create a helper method <strong>getTranslation<\/strong>\u00a0which uses the model name and attribute name\u00a0to get the translation using that structure we defined in the translations file (model.modelName.attribute).<\/p>\n<p>Since we also pass the attribute name from the\u00a0application template, we have everything we need. Just need to update the application template and remove the label and placeholder parameters:<\/p>\n<pre>{{attribute-text\r\n  model=model\r\n  attribute='name'\r\n  onUpdateValue=(action 'setName')\r\n}}<\/pre>\n<p>Also, we can now include the help text that is present in the translations file, in the component template file, like this (relevant\u00a0<a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/f4a15598e405d1eb5456bad4cf734c0d803108fc\">commit<\/a>):<\/p>\n<pre>{{#if hasHelp}}\r\n  &lt;span class=\"help-block\"&gt;{{helpText}}&lt;\/span&gt;\r\n{{\/if}}<\/pre>\n<p>In order to switch between locales we can add two buttons and an action to\u00a0our controller<\/p>\n<pre>templates\/application.hbs\r\n&lt;button class='btn btn-default' disabled={{eq i18n.locale 'en'}} onClick={{action 'setLocale' 'en'}}&gt;English&lt;\/button&gt;\r\n&lt;button class='btn btn-default' disabled={{eq i18n.locale 'pt'}} onClick={{action 'setLocale' 'pt'}}&gt;Portugu\u00eas&lt;\/button&gt;<\/pre>\n<p>And an action in the controller<\/p>\n<pre>controllers\/application.js\r\n\r\nconst {\r\n  Controller,\r\n  get,\r\n  inject: { service }\r\n} = Ember;\r\n\r\nexport default Controller.extend({\r\n  i18n: service(),\r\n\r\n  actions: {\r\n    ...\r\n    setLocale(value) {\r\n      this.set('i18n.locale', value);\r\n    }\r\n  }\r\n}<\/pre>\n<p>And with this (<a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/690a6743015f5bea1768cc3fb9f53b43796879fc\">see this commit<\/a>), we finish the first part regarding conventions. We basically leverage a predefined structure (convention) in the translations file and the fact that each instance of a model knows the name of the model to retrieve\u00a0all the values associated with a given attribute.<\/p>\n<h1>Part 2 &#8211; Preventing bugs\/typos on attribute names using conventions<\/h1>\n<p>One of the things\u00a0that I find a real problem is doing things like we did before while setting the value on the model:<\/p>\n<pre>setName(name) {\r\n let model = get(this, 'model');\r\n model.set('name', name);\r\n},<\/pre>\n<p>Doing a <strong>set <\/strong>operation and passing a string like\u00a0<strong>&#8216;name&#8217; <\/strong>means that if we make a small typo on that &#8216;name&#8217;, we never find out about it until we go hunting a bug because some operation\u00a0that depends on this value\u00a0is having a weird behavior. This is\u00a0a mistake I&#8217;ve done plenty of times, and the way I found to deal with my typos is the following:<\/p>\n<p>I create a file in the utils folder of my app called <em>person-utils.js<\/em> in which I place the following content:<\/p>\n<pre>utils\/person-utils.js\r\nexport default {\r\n PERSON: {\r\n  NAME: 'name',\r\n  AGE: 'age'\r\n }\r\n};<\/pre>\n<p>This is basically a list of all attributes of the model\u00a0Person, but as a JSON object that I can reference.<\/p>\n<p>In my controller I now import this file and create a new method:<\/p>\n<pre>controllers\/application.js\r\ni18n: service(),\r\n...\r\nsetField(field, value) {\r\n Ember.assert(`Must pass a valid attribute - ${field}`, !isEmpty(field));\r\n let model = get(this, 'model');\r\n model.set(field, value);\r\n},<\/pre>\n<p>This method will be used to set the value of a field and assert that the field name is valid (as in, not empty), for this to work now we have to change our controller to look like this:<\/p>\n<pre>controllers\/application.js\r\nimport Ember from 'ember';\r\nimport PersonUtil from '..\/utils\/person';\r\n\r\nconst {\r\n Controller,\r\n get,\r\n inject: { service },\r\n assert,\r\n isEmpty\r\n} = Ember;\r\n\r\nconst {\r\n PERSON\r\n} = PersonUtil;\r\n\r\nexport default Controller.extend({\r\n\r\n setField(field, value) {\r\n   assert(`Must pass a valid attribute - ${field}`, !isEmpty(field));\r\n   let model = get(this, 'model');\r\n   model.set(field, value);\r\n },\r\n\r\n actions: {\r\n   setName(name) {\r\n    this.setField(PERSON.NAME, name);\r\n   },\r\n\r\n   setAge(age) {\r\n    this.setField(PERSON.AGE, name);\r\n   }\r\n }\r\n});<\/pre>\n<p>By importing the <strong>person-utils<\/strong> file with the constant <strong>PERSON<\/strong> which contains keys for each attribute, and using the calls to setField with a key from that object, If I make a mistake and do:<\/p>\n<pre>this.setField(PERSON.NEME); \/\/ This will fail because NEME does not exist<\/pre>\n<p>When I try\u00a0to write on\u00a0the name field, I&#8217;ll get a nice error message in the console, and even a stacktrace telling me where the problem is, like the following example:<\/p>\n<div id=\"attachment_448\" style=\"width: 810px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-448\" class=\"size-full wp-image-448\" src=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter.jpg\" alt=\"Wrong parameter\" width=\"800\" height=\"177\" srcset=\"http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter.jpg 800w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter-300x66.jpg 300w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter-768x170.jpg 768w, http:\/\/www.corrspt.com\/blog\/wp-content\/uploads\/2016\/11\/error-wrong-parameter-500x111.jpg 500w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-448\" class=\"wp-caption-text\">Wrong parameter<\/p><\/div>\n<p>The list of changes <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/735c5bc098de76d9d3bc5239147097ca3c8aa68b\">can be seen in this commit<\/a>.\u00a0This has prevented me a lot of bugs \ud83d\ude42<\/p>\n<h1>Real-time\u00a0validation<\/h1>\n<p>The last step in this tutorial is having\u00a0validation as you type. In order to do that we must define a set of validations as per <a href=\"https:\/\/github.com\/esbanarango\/ember-model-validator\">ember-model-validator<\/a>&#8216;s documentation, so we change our model to have the following (age must be an integer over 18 and name a string over 4 characters long):<\/p>\n<pre>models\/person.js\r\nimport Validator from '..\/mixins\/model-validator';\r\n\r\nconst {\r\n Model,\r\n attr\r\n} = DS;\r\n\r\nexport default Model.extend(Validator, {\r\n name: attr('string'),\r\n age: attr('number'),\r\n validations: {\r\n  name: {\r\n    presence: true,\r\n    length: {\r\n    minimum: 4\r\n   }\r\n  },\r\n  age: {\r\n   presence: true,\r\n    numericality: {\r\n     allowBlank: true,\r\n     onlyInteger: true,\r\n     greaterThanOrEqualTo: 18\r\n   }\r\n  }\r\n }<\/pre>\n<p>Now, we need to update our component to display errors, which per bootstrap&#8217;s documentation is adding an &#8220;has-error&#8221; class to the outer div and a span with class &#8220;help-block&#8221; to display the messages.<\/p>\n<pre>&lt;div class=\"form-group {{if (gt (get model (concat 'errors.' attribute '.length')) 0) 'has-error'}}\"&gt;\r\n   &lt;label title=\"{{placeholder}}\" class='control-label' for='{{attribute}}'&gt;\r\n   {{label}}\r\n   &lt;\/label&gt;\r\n   &lt;input\r\n    value={{get model attribute}}\r\n    oninput={{action this.attrs.onUpdateValue value=\"target.value\"}}\r\n    class='form-control'\r\n    placeholder={{placeholder}}\r\n    type='text'\r\n    id={{attribute}}\r\n  &gt;\r\n {{#each (get model (concat 'errors.' attribute)) as |error|}}\r\n   &lt;span class=\"help-block\"&gt;{{error.message}}&lt;\/span&gt;\r\n {{\/each}}\r\n {{#if hasHelp}}\r\n   &lt;span class=\"help-block\"&gt;{{helpText}}&lt;\/span&gt;\r\n {{\/if}}\r\n&lt;\/div&gt;<\/pre>\n<p>We use the &#8220;gt&#8221; helper for <a href=\"https:\/\/github.com\/jmurphyau\/ember-truth-helpers\">ember-truth-helpers<\/a> for check if the model has errors on the attribute that is linked to this component and if so, we add the &#8220;has-error&#8221; class.<\/p>\n<p>With this now we are capable of showing errors, but we&#8217;re missing something that triggers the validation process. Since I want to have &#8220;real-time&#8221; validation, I&#8217;m going to use the actions\u00a0in the controller that update the model, to also validate the field which I&#8217;m typing on.<\/p>\n<pre>controllers\/application.js\r\nvalidateField(field) {\r\n this.get('model').validate({ only: [field] });\r\n},\r\n\r\nsetField(field, value) {\r\n assert(`Must pass a valid attribute - ${field}`, !isEmpty(field));\r\n let model = get(this, 'model');\r\n model.set(field, value);\r\n this.validateField(field);\r\n},<\/pre>\n<p>These changes can be <a href=\"https:\/\/github.com\/corrspt\/blog-post-ember-convertions-steps\/commit\/a8ab06664a997f71176ce7849fa9be6bdd5050f3\">seen in the relevant commit<\/a>.<\/p>\n<p>EmberJS is a really great framework which leverages a lot of conventions (especially when coupled with the excellent ember-cli tools), by adding a few more\u00a0of our own conventions on top of this project I think we get even more value.<\/p>\n<p>Feel free to comment and suggest better approaches.<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I want to talk about conventions and share something I&#8217;ve been doing as I&#8217;m working in my app that uses EmberJS\u00a0for the front-end. Warning: This post\u00a0does assume a certain degree of familiarity with\u00a0ember\/ember-cli and I assume that you have &hellip; <a href=\"http:\/\/www.corrspt.com\/blog\/2016\/11\/28\/ember-conventions-over-conventions\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,12],"tags":[57,49],"class_list":["post-444","post","type-post","status-publish","format-standard","hentry","category-emberjs","category-web-development","tag-ember","tag-emberjs"],"_links":{"self":[{"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/posts\/444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/comments?post=444"}],"version-history":[{"count":6,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/posts\/444\/revisions"}],"predecessor-version":[{"id":453,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/posts\/444\/revisions\/453"}],"wp:attachment":[{"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/media?parent=444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/categories?post=444"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.corrspt.com\/blog\/wp-json\/wp\/v2\/tags?post=444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}