Last active
June 3, 2022 10:07
-
-
Save pablobm/e77a98e5f3c610953a82 to your computer and use it in GitHub Desktop.
Revisions
-
pablobm revised this gist
Oct 23, 2016 . 1 changed file with 19 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -319,12 +319,6 @@ Still, `Model#rollbackAttributes` is the best way to do it. It is usable in two different situations, and it saves you checking for `record.get('isNew')`. ## Alternative: use buffer object as models Using `Store#createRecord` on the `new` route has two gotchas: @@ -371,6 +365,25 @@ However, this doesn't entirely work: anyway, and it will appear on the list after transitioning away. ## Validation errors on the object as a whole Remember that validation errors can be associated to a record as a whole, as opposed to individual fields. Maybe you were trying to buy an item that run out, or there's an invalid interaction between several fields that cannot be blamed on a specific one. This would be communicated to the user with a "general" error message instead of flagging a section of a form. As far as I know, there's no common convention for addressing this, and different backend frameworks may (or may not) offer support for it in different ways. For example, Ruby on Rails used to address this case with an explicit API, but this has since been dropped. Nowadays, you would be expected to list these errors as if they were part of a field that is not really on the form. Your code may want to check on this pseudo-attribute too. In Ruby on Rails, this is normally called `base`, so in this case you'd want to make sure to display any errors on `model.errors.base`. ## See also... Resources I have found or been pointed to. I'm currently going through them: -
Pablo Brasero revised this gist
Oct 21, 2016 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -241,12 +241,15 @@ losing the state of the app. Avoid. Do use closure actions with Ember components though. They are great. ## `willTransition` and `didTransition` When detecting a move away from the route, prefer `willTransition` over `deactivate`. This is because the latter doesn't fire when **only the model** changes. For the same reason, to detect a successful landing on a route, prefer `didTransition` over `activate`. This may not sound relevant, but consider the following example. Say you extend the `edit` route to show a list of existing records (like the `index` route). As you edit the record, you'll see -
Pablo Brasero revised this gist
Jul 1, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -79,7 +79,7 @@ name of the model. This is, they read `:line_id` instead of just `:id`. This is because: * The default implementation of `Route#model` (the `model()` hook in routes) expects this name (see "The `model()` hook" below). * It is necessary anyway when working with nested models. Eg: `/receipt/:receipt_id/lines/:line_id` -
Pablo Brasero revised this gist
Jul 1, 2016 . 5 changed files with 45 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -70,9 +70,18 @@ action are the following: * `/lines` - list existing records * `/lines/new` - create a new record * `/lines/:line_id` - show a single record * `/lines/:line_id/edit` - edit and update a single record * `/lines/:line_id/destroy` - delete a record, but confirm first Unlike the usual basic Rails paths though, the `id` segments include the name of the model. This is, they read `:line_id` instead of just `:id`. This is because: * The default implementation of `Route#model` (the `model()` hook in routes) expects this name (see "The model() hook" below). * It is necessary anyway when working with nested models. Eg: `/receipt/:receipt_id/lines/:line_id` ## The `index` route @@ -97,9 +106,35 @@ this.transitionTo('lines'); this.transitionTo('lines.index'); ``` ## The `model()` hook (or its absence) `Route#model()` has a default implementation that may work for you already. If the last segment parameter of your path (eg: `:line_id` in `/receipts/:receipt_id/lines/:line_id`) matches the format `:{NAME}_id`, Ember will assume that `{NAME}` is the name of your model, and will fetch it from the store with `this.store.find('{NAME}', params.{NAME}_id)`. Therefore, if you follow the convention of having a segment `:line_id`, you may not need to implement the `model()` hook at all. ## The `show` route can be missing too Following on the previous point, you may not need to provide an explicit `show` route: 1. Ember will provide implicit routes for any routes mentioned in `app/router.js` 2. An implicit route is equivalent to an empty route. In other words: a route that extends `Ember.Route` but doesn't add anything to it 3. `Ember.Route` has an implementation of the `model()` hook, which will be used in an empty route Remember that you will still need to provide a template. ## `find`-er methods If you still need to grab a record from the store, use `Store#findRecord`, not `Store#find`. Before Ember Data 1.13, you would retrieve records with the methods `Store#find`, `Store#all`, `Store#getById` and others. These have been @@ -119,7 +154,7 @@ not notice. However, it's marked private on Ember Data's source code, and usage by your code is discouraged. It has been kept around for compatibility reasons, because Ember (which is separate from Ember Data) uses it for the default implementation of the `Route#model()` hook. Check out the source code for [more information](https://github.com/emberjs/data/blob/master/addon/-private/system/store.js#L385). ## Accessing the current model This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,10 +8,10 @@ const Router = Ember.Router.extend({ Router.map(function() { this.route('lines', function() { this.route('new'); this.route('show', {path: ':line_id'}); this.route('edit', {path: ':line_id/edit'}); this.route('destroy', {path: ':line_id/destroy'}); }); }); export default Router; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,14 +1,10 @@ import Ember from 'ember'; export default Ember.Route.extend({ actions: { confirm(record) { record.destroyRecord() .then(() => this.transitionTo('lines')); }, } }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,6 @@ import Ember from 'ember'; export default Ember.Route.extend({ actions: { save(record) { record.save() This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +0,0 @@ -
pablobm revised this gist
May 29, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -233,7 +233,7 @@ Quoth @rwjblue (https://youtu.be/7kU5lLnEtJs?t=4m24s): > framework hook. Period. End of story. Even if you know it > doesn’t need to be done, you should do it. Therefore, always call `this._super(...arguments)` on Ember hooks. This includes `willTransition`. ## Discarding changes to a record -
pablobm revised this gist
May 29, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -200,7 +200,7 @@ action as follows: <form onsubmit={{action 'confirm' model}}> ``` This will not stop the `submit` event in any way. As a result, the browser will attempt to submit the form, causing a page refresh and losing the state of the app. Avoid. -
pablobm revised this gist
May 29, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -66,7 +66,7 @@ which is a string. ## Routes Following Ruby on Rails's lead, the paths/routes for each CRUD action are the following: * `/lines` - list existing records * `/lines/new` - create a new record -
Pablo Brasero revised this gist
May 12, 2016 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,8 @@ # CRUD with Ember (+ Data)   Ember's official documentation describes a number of low-level APIs, but doesn't talk much about how to put them together. As a result, a simple task such as creating a simple CRUD -
Pablo Brasero revised this gist
May 12, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,7 +10,7 @@ and document a clear convention for simple CRUD apps, using Ember and Ember Data with no third-party add-ons. I hope this will be a useful resource for beginners who, fresh out of reading the [Guides](https://guides.emberjs.com), could use more directions on basic conventions, idioms and patterns in use by the Ember community. I also hope to benefit myself personally, when readers point out mistakes (which will -
Pablo Brasero revised this gist
May 11, 2016 . 1 changed file with 25 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -178,6 +178,31 @@ to get forms to work as they should: This should get you some extra usability and accessibility brownie points, if only because that's the way forms are intended to work. ## Capture DOM events with "classic" actions DOM events, such as `click` or `submit` (among others) should be captured using "classic" actions, as opposed to "closure" actions. Example follows: ```handlebars <form {{action 'confirm' model on='submit'}}> ``` This is because classic actions stop the propagation and the default behaviour of these events, whereas closure actions don't. For example, say that we capture the `submit` event with a closure action as follows: ```handlebars <form onsubmit={{action 'confirm' model}}> ``` This will not stop the `submit` event in anyway. As a result, the browser will attempt to submit the form, causing a page refresh and losing the state of the app. Avoid. Do use closure actions with Ember components though. They are great. ## `willTransition` When detecting a move away from the route, prefer `willTransition` -
Pablo Brasero revised this gist
May 11, 2016 . 2 changed files with 8 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -154,16 +154,17 @@ purpose: initially it will work but, since it's a private API, who knows how it could break in the future. ## Trigger actions on form submission On forms, it's tempting to associate the `save` action (or similar) with clicking a button. In fact, that's what the guides teach you to do: ```html <button {{action 'save' model}}>Save</button> ``` But then we cannot press *Enter* on text fields to save. Remember that, on the web, data is submitted on a `submit` event. Use this to get forms to work as they should: This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ <p>Are you sure?</p> <form {{action 'confirm' model on='submit'}}> <p><button>Delete <strong>{{model.name}}</strong></button> or {{#link-to 'lines'}}cancel{{/link-to}}</p> </form> -
Pablo Brasero revised this gist
May 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -236,7 +236,7 @@ if (record.get('isNew')) { Now, to actually delete the record, we have these options: * `Model#deleteRecord`: between Ember Data v2.0.0.beta1 and v2.5.0, a bug made this not work correctly when the record is unsaved but has errors. Ie: the user fills out the form, the app tries to save, server-side validation returns errors, the model has its `Model#errors` populated. -
Pablo Brasero revised this gist
May 11, 2016 . 2 changed files with 38 additions and 31 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -207,41 +207,50 @@ Quoth @rwjblue (https://youtu.be/7kU5lLnEtJs?t=4m24s): Therefore, always `this._super(...arguments)` on Ember hooks. This includes `willTransition`. ## Discarding changes to a record To discard changes to a record, use `Model#rollbackAttributes`: * When updating an existing record, it will discard any unsaved changes. * When creating a new record, it will drop it from the store. Since it works in both cases, it opens up new opportunities for reusing code. For example in the form of mixins. There's something slightly annoying with the name `rollbackAttributes`, and it is that it conveys the meaning "discard unsaved changes", but not so much "drop unsaved records". Still, this is the accepted way of doing things, and is documented on the guides and the API docs. For the specific case of dropping unsaved records, there are other alternatives. You can check if the record has been saved, and delete it if not. It would be something like this: ```js if (record.get('isNew')) { // Delete the record here } ``` Now, to actually delete the record, we have these options: * `Model#deleteRecord`: between Ember Data v2.0.0.beta1 and v2.5.0, and bug made this not work correctly when the record is unsaved but has errors. Ie: the user fills out the form, the app tries to save, server-side validation returns errors, the model has its `Model#errors` populated. * `Model#destroyRecord`: same as `deleteRecord`, but also tries to persist the deletion of this actually-not-persisted record. For this, it makes a request to `DELETE /{model-name}/{id}` but, since there's no id yet, it ends up being `DELETE /{model-name}`. * `Store#unloadRecord`: this actually works well Still, `Model#rollbackAttributes` is the best way to do it. It is usable in two different situations, and it saves you checking for `record.get('isNew')`. ## Validation errors on `base` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,9 +14,7 @@ export default Ember.Route.extend({ willTransition() { this._super(...arguments); const record = this.controller.get('model'); record.rollbackAttributes(); }, }, }); -
Pablo Brasero revised this gist
May 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -40,7 +40,7 @@ This is what I expect from this convention: The adapter/serializer parts are supposed to be working and are not relevant 3. Validation will happen server-side 4. The interface will accomodate for the possibility of validation errors ## This is not very DRY -
Pablo Brasero revised this gist
Apr 25, 2016 . 1 changed file with 24 additions and 24 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -60,30 +60,6 @@ This example assumes the model is called `line`. It's defined as an Ember Data model and it only has one attribute: `name`, which is a string. ## Routes Following Ruby on Rails's lead, the paths/routes for each CRUD @@ -118,6 +94,30 @@ this.transitionTo('lines'); this.transitionTo('lines.index'); ``` ## `find`-er methods Use `Store#findRecord`, not `Store#find`. Before Ember Data 1.13, you would retrieve records with the methods `Store#find`, `Store#all`, `Store#getById` and others. These have been deprecated and removed. These are the methods you should be using now, as seen on the [Ember Data 1.13 release announcement](http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html): | | Async from server/store | Sync from store | Query server | |---------------|-------------------------|----------------------|----------------------------| | Single Record | findRecord(type,id) | peekRecord(type, id) | queryRecord(type, {query}) | | All Records | findAll(type) | peekAll(type) | query(type, {query}) | I told a little lie though: `Store#find` hasn't been removed, and it won't even trigger a deprecation alert. You could use it and would not notice. However, it's marked private on Ember Data's source code, and usage by your code is discouraged. It has been kept around for compatibility reasons, because Ember (which is separate from Ember Data) uses it for the default implementation of the `Route#model` hook. Check out the source code for [more information](https://github.com/emberjs/data/blob/master/addon/-private/system/store.js#L385). ## Accessing the current model There seem to be two accepted ways of obtaining the current model -
Pablo Brasero revised this gist
Apr 20, 2016 . 1 changed file with 46 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -249,6 +249,52 @@ Remember that validation errors can be associated to a record's `base`, not only to its properties. You may want to check if there's anything to display on `model.errors.base`. ## Alternative: use buffer object as models Using `Store#createRecord` on the `new` route has two gotchas: 1. As seen above, we have to remember to undo the changes if we cancel (ie: transition away without saving) 2. If we are showing a list of records on the same page where the creation form is, we'll see the "ghost", new record appear unless we explicitly filter it out Some people then prefer using a "buffer" object that holds the values for the new object, without adding it to the store until the user decides to save. This can be done with a plain JS object: ```js import Ember from 'ember'; export default Ember.Route.extend({ model() { return {}; }, actions: { save(record) { const model = this.store.createRecord('line', record); model.save() .then(() => this.transitionTo('lines')); }, }, }); ``` Note that this tackles both issues: we don't need to worry about handling the `willTransition` event, and the new record won't be listed in the store until it's finally saved. However, this doesn't entirely work: 1. Validation errors will not be added to the buffer object, and therefore won't be rendered on the form. 2. On error, the record will have been added to the store anyway, and it will appear on the list after transitioning away. ## See also... Resources I have found or been pointed to. I'm currently going through them: -
Pablo Brasero revised this gist
Apr 20, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -82,7 +82,7 @@ not notice. However, it's marked private on Ember Data's source code, and usage by your code is discouraged. It has been kept around for compatibility reasons, because Ember (which is separate from Ember Data) uses it for the default implementation of the `Route#model` hook. Check out the source code for [more information](https://github.com/emberjs/data/blob/master/addon/-private/system/store.js#L385). ## Routes -
Pablo Brasero revised this gist
Apr 19, 2016 . 1 changed file with 24 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -60,6 +60,30 @@ This example assumes the model is called `line`. It's defined as an Ember Data model and it only has one attribute: `name`, which is a string. ## `find`-er methods Use `Store#findRecord`, not `Store#find`. Before Ember Data 1.13, you would retrieve records with the methods `Store#find`, `Store#all`, `Store#getById` and others. These have been deprecated and removed. These are the methods you should be using now, as seen on the [Ember Data 1.13 release announcement](http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html): | | Async from server/store | Sync from store | Query server | |---------------|-------------------------|----------------------|----------------------------| | Single Record | findRecord(type,id) | peekRecord(type, id) | queryRecord(type, {query}) | | All Records | findAll(type) | peekAll(type) | query(type, {query}) | I told a little lie though: `Store#find` hasn't been removed, and it won't even trigger a deprecation alert. You could use it and would not notice. However, it's marked private on Ember Data's source code, and usage by your code is discouraged. It has been kept around for compatibility reasons, because Ember (which is separate from Ember Data) uses it for the default implementation of the `Route#model` hook. ## Routes Following Ruby on Rails's lead, the paths/routes for each CRUD -
pablobm revised this gist
Apr 19, 2016 . 2 changed files with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.findRecord('line', params.id); }, actions: { This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.findRecord('line', params.id); }, actions: { -
pablobm revised this gist
Apr 19, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.find('line', params.id); }, actions: { -
Pablo Brasero revised this gist
Apr 13, 2016 . 3 changed files with 15 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -172,6 +172,17 @@ The original record will remain edited (not rolled back), but won't have been persisted. After reloading the page, the change will disappear. ## Always call `_super` on hooks Quoth @rwjblue (https://youtu.be/7kU5lLnEtJs?t=4m24s): > You should always call `_super` whenever you implement any > framework hook. Period. End of story. Even if you know it > doesn’t need to be done, you should do it. Therefore, always `this._super(...arguments)` on Ember hooks. This includes `willTransition`. ## `unloadRecord` To discard an newly created, unsaved record, use `Store#unloadRecord`. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,8 +12,9 @@ export default Ember.Route.extend({ }, willTransition() { this._super(...arguments); const record = this.controller.get('model'); record.rollbackAttributes(); }, }, }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,10 +12,11 @@ export default Ember.Route.extend({ }, willTransition() { this._super(...arguments); const record = this.controller.get('model'); if (record.get('isNew')) { this.store.unloadRecord(record); } }, }, }); -
Pablo Brasero revised this gist
Apr 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -122,7 +122,7 @@ purpose: * Implementing `setupController(ctrl, model)` and capturing the model there. This is a bit convoluted, and involves two subtle risks. The first one is that you may forget calling `this._super(ctrl, model)` and wonder why your app doesn't work. The second is that you may then do `this.model = model` and overwrite the `model()` function, breaking the route in later invocations. There's a similar risk if you overwrite -
Pablo Brasero revised this gist
Apr 11, 2016 . 1 changed file with 29 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -96,18 +96,39 @@ this.transitionTo('lines.index'); ## Accessing the current model There seem to be two accepted ways of obtaining the current model from a route (eg: from an action handler): ```js // These two should be equivalent this.controller.get('model'); this.modelFor(this.routeName); ``` I personally prefer the first of the two, for aesthetic reasons more than anything. Some people are concerned that "controllers will be removed from Ember in the future", but the core team reassures us that this is not going to happen any time soon, and the replacement code will be very similar. If you want to future-proof your application, there are better places to spend your time than in avoiding controllers. In the wild, you may see other techniques that achieve the same purpose: * Reading from `this.currentModel`. A private, undocumented API. Don't expect it to be there tomorrow * Implementing `setupController(ctrl, model)` and capturing the model there. This is a bit convoluted, and involves two subtle risks. The first one is that you may forget calling `this.super(ctrl, model)` and wonder why your app doesn't work. The second is that you may then do `this.model = model` and overwrite the `model()` function, breaking the route in later invocations. There's a similar risk if you overwrite `this.currentModel`, but more exciting. Exciting because initially it will work but, since it's a private API, who knows how it could break in the future. ## Trigger `save` on form submit -
Pablo Brasero revised this gist
Apr 11, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -187,7 +187,7 @@ It's possible to achieve the same effect using `Model#rollbackAttributes`: record is not deleted (when it actually is) 2. It doesn't mirror `Store#createRecord` like `Store#unloadRecord` does ## Validation errors on `base` Remember that validation errors can be associated to a record's `base`, not only to its properties. You may want to check if there's anything -
Pablo Brasero revised this gist
Apr 11, 2016 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,10 +10,10 @@ and document a clear convention for simple CRUD apps, using Ember and Ember Data with no third-party add-ons. I hope this will be a useful resource for beginners who, fresh out of reading the [Guides](https://guides.emberjs.com/v2.4.0/), could use more directions on basic conventions, idioms and patterns in use by the Ember community. I also hope to benefit myself personally, when readers point out mistakes (which will be corrected) and bring up differing opinions (which will be considered). -
Pablo Brasero revised this gist
Apr 11, 2016 . 1 changed file with 16 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,6 +17,12 @@ personally, when readers point out mistakes (which will be corrected) and bring up differing opinions (which will be considered). The following sections discuss considerations taken when creating this convention. See the final code files listed separately further down. This is a **work in progress**. ## General principles This implementation is heavily influenced by the style of @@ -37,13 +43,7 @@ This is what I expect from this convention: 4. The interface must be accomodate for the possibility of validation errors ## This is not very DRY This code could use mixins and components to avoid repetition. However I am avoiding this because: @@ -54,13 +54,13 @@ However I am avoiding this because: If you use this code, you may want to DRY it up as suggested. ## The model This example assumes the model is called `line`. It's defined as an Ember Data model and it only has one attribute: `name`, which is a string. ## Routes Following Ruby on Rails's lead, the paths/routes for each CRUD acion are the following: @@ -71,7 +71,7 @@ acion are the following: * `/lines/:id/edit` - edit and update a single record * `/lines/:id/destroy` - delete a record, but confirm first ## The `index` route Ember automatically assumes that there is an `index` route when we nest routes. Therefore,we **don't** need @@ -94,7 +94,7 @@ this.transitionTo('lines'); this.transitionTo('lines.index'); ``` ## Accessing the current model The correct way to obtain the current model from the route (eg: from an action handler) is: @@ -109,7 +109,7 @@ I have seen other options, but I don't like them: expect it to be there tomorrow * `this.modelFor('foo.bar.baz')`: un-DRY and inconvenient ## Trigger `save` on form submit It's tempting to associate the `save` action with clicking a button: @@ -132,7 +132,7 @@ to get forms to work as they should: This should get you some extra usability and accessibility brownie points, if only because that's the way forms are intended to work. ## `willTransition` When detecting a move away from the route, prefer `willTransition` over `deactivate`. This is because the latter doesn't fire @@ -151,7 +151,7 @@ The original record will remain edited (not rolled back), but won't have been persisted. After reloading the page, the change will disappear. ## `unloadRecord` To discard an newly created, unsaved record, use `Store#unloadRecord`. From the guides, it would appear that `Model#deleteRecord` and @@ -172,7 +172,7 @@ behaviour of `deleteRecord` is a bug, acknowledged at https://github.com/emberjs Still, I have a preference for `Store#unloadRecord` as it mirrors the previous `Store#createRecord`. ### Other alternatives It's possible to achieve the same effect using `Model#rollbackAttributes`: @@ -186,7 +186,7 @@ It's possible to achieve the same effect using `Model#rollbackAttributes`: because is sounds like the attributes are restored (to blank), but the record is not deleted (when it actually is) 2. It doesn't mirror `Store#createRecord` like `Store#unloadRecord` does ### Validation errors on `base` Remember that validation errors can be associated to a record's `base`, @@ -200,7 +200,3 @@ Resources I have found or been pointed to. I'm currently going through them: * [A List of Open Source EmberJS Applications](http://iheanyi.com/blog/a-list-of-open-source-emberjs-projects/) by [Iheanyi Ekechukwu](http://iheanyi.com) * [Ember.js 2 Tutorial](http://yoember.com/) by [Zoltan Debre](http://zoltan.nz/) * [ember-cli-scaffold](https://github.com/marcioj/ember-cli-scaffold) by [Marcio Junior](https://github.com/marcioj) -
pablobm revised this gist
Apr 8, 2016 . 1 changed file with 6 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -36,7 +36,6 @@ This is what I expect from this convention: 3. Validation will happen server-side 4. The interface must be accomodate for the possibility of validation errors ## Implementation details @@ -187,6 +186,12 @@ It's possible to achieve the same effect using `Model#rollbackAttributes`: because is sounds like the attributes are restored (to blank), but the record is not deleted (when it actually is) 2. It doesn't mirror `Store#createRecord` like `Store#unloadRecord` does ### Validation errors on `base` Remember that validation errors can be associated to a record's `base`, not only to its properties. You may want to check if there's anything to display on `model.errors.base`. ## See also... -
Pablo Brasero revised this gist
Apr 8, 2016 . 1 changed file with 23 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -110,6 +110,29 @@ I have seen other options, but I don't like them: expect it to be there tomorrow * `this.modelFor('foo.bar.baz')`: un-DRY and inconvenient ### Trigger `save` on form submit It's tempting to associate the `save` action with clicking a button: ```html <button {{action 'save' model}}>Save</button> ``` But then we cannot press *Enter* on the text field to save. Remember that, on the web, data is submitted on a `submit` event. Use this to get forms to work as they should: ```html <form {{action 'save' model on='submit'}}> <!-- ...form fields... --> <button>Save</button> </form> ``` This should get you some extra usability and accessibility brownie points, if only because that's the way forms are intended to work. ### `willTransition` When detecting a move away from the route, prefer `willTransition` -
pablobm revised this gist
Apr 8, 2016 . 2 changed files with 20 additions and 16 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,12 @@ <form {{action 'save' model on='submit'}}> {{#each model.errors.base as |error|}} <p class="error">{{error.message}}</p> {{/each}} <p>{{input value=model.name placeholder="Name" name="name"}}</p> {{#each model.errors.name as |error|}} <p class="error">{{error.message}}</p> {{/each}} <p><button>Update</button> or {{#link-to 'lines'}}Cancel{{/link-to}}</p> </form> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,12 @@ <form {{action 'save' model on='submit'}}> {{#each model.errors.base as |error|}} <p class="error">{{error.message}}</p> {{/each}} <p>{{input value=model.name placeholder="Name" name="name"}}</p> {{#each model.errors.name as |error|}} <p class="error">{{error.message}}</p> {{/each}} <p><button>Create</button> or {{#link-to 'lines'}}Cancel{{/link-to}}</p> </form> -
pablobm revised this gist
Apr 7, 2016 . 1 changed file with 15 additions and 15 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -95,6 +95,21 @@ this.transitionTo('lines'); this.transitionTo('lines.index'); ``` ### Accessing the current model The correct way to obtain the current model from the route (eg: from an action handler) is: ```js this.controller.get('model') ``` I have seen other options, but I don't like them: * `this.currentModel`: it's a private, undocumented API. Don't expect it to be there tomorrow * `this.modelFor('foo.bar.baz')`: un-DRY and inconvenient ### `willTransition` When detecting a move away from the route, prefer `willTransition` @@ -150,21 +165,6 @@ It's possible to achieve the same effect using `Model#rollbackAttributes`: record is not deleted (when it actually is) 2. It doesn't mirror `Store#createRecord` like `Store#unloadRecord` does ## See also... Resources I have found or been pointed to. I'm currently going through them:
NewerOlder