diff --git a/.editorconfig b/.editorconfig index 2fe4874..47c5438 100644 --- a/.editorconfig +++ b/.editorconfig @@ -18,6 +18,7 @@ indent_style = space indent_size = 2 [*.hbs] +insert_final_newline = false indent_style = space indent_size = 2 diff --git a/.ember-cli b/.ember-cli index 26cfcf3..ee64cfe 100644 --- a/.ember-cli +++ b/.ember-cli @@ -5,6 +5,5 @@ Setting `disableAnalytics` to true will prevent any data from being sent. */ - "disableAnalytics": false, - "liveReload": false /* Set to false for non web-socket browser debugging */ + "disableAnalytics": false } diff --git a/.npmignore b/.npmignore index a28e4ab..49996f5 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,7 @@ bower_components/ tests/ tmp/ +dist/ .bowerrc .editorconfig diff --git a/.travis.yml b/.travis.yml index cf23938..b2f7d35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ --- language: node_js +node_js: + - "0.12" sudo: false @@ -7,7 +9,24 @@ cache: directories: - node_modules +env: + - EMBER_TRY_SCENARIO=default + - EMBER_TRY_SCENARIO=ember-release + - EMBER_TRY_SCENARIO=ember-beta + - EMBER_TRY_SCENARIO=ember-canary + +matrix: + fast_finish: true + allow_failures: + - env: EMBER_TRY_SCENARIO=ember-release # https://github.com/rwjblue/ember-qunit/issues/178 + - env: EMBER_TRY_SCENARIO=ember-beta + - env: EMBER_TRY_SCENARIO=ember-canary + before_install: + - mkdir travis-phantomjs + - wget https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 + - tar -xvf $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -C $PWD/travis-phantomjs + - export PATH=$PWD/travis-phantomjs:$PATH - "npm config set spin false" - "npm install -g npm@^2" @@ -17,4 +36,4 @@ install: - bower install script: - - npm test + - ember try $EMBER_TRY_SCENARIO test diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 0000000..5e9462c --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1,3 @@ +{ + "ignore_dirs": ["tmp"] +} diff --git a/Brocfile.js b/Brocfile.js index fdce144..2a682c0 100644 --- a/Brocfile.js +++ b/Brocfile.js @@ -3,23 +3,14 @@ var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); -var app = new EmberAddon({ - vendorFiles: { - 'handlebars.js': null - } -}); +/* + This Brocfile specifes the options for the dummy test app of this + addon, located in `/tests/dummy` -// Use `app.import` to add additional libraries to the generated -// output files. -// -// If you need to use different assets in different -// environments, specify an object as the first parameter. That -// object's keys should be the environment name and the values -// should be the asset to use in that environment. -// -// If the library that you are including contains AMD or ES6 -// modules that you would like to import into your application -// please specify an object with the list of modules as keys -// along with the exports of each module as its value. + This Brocfile does *not* influence how the addon or the app using it + behave. You most likely want to be modifying `./index.js` or app's Brocfile +*/ + +var app = new EmberAddon(); module.exports = app.toTree(); diff --git a/README.md b/README.md index ea8730c..609d7c8 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,17 @@ -# Ember Easy Form Extensions +Ember Easy Form Extensions [](https://travis-ci.org/sir-dunxalot/ember-easy-form-extensions) +====== -This addon extends Ember EasyForm into the view and controller layers of your Ember CLI app to provide easy event and action handling using mixins and components. The newly accessible developer-friendly layer includes form submission handlers, components, and integration with ember-validations. +This Ember addon enhances Ember EasyForm by providing easy action handling, validations, and Ember 1.13 support for your forms -**This is also the easiest known way to use Easy Form with Ember 1.10 and HTMLBars.** +**To support Ember 1.13 Easy Form has been temporarily rewritten for Ember CLI. When EasyForm is updated by Dockyard this addon will support that instead of our own form components.** -## Ember 1.11+ Users - -Whilst this addon's master branch currently supports Ember 1.10, there are even more known issues with Ember Easy Forms and Ember 1.11. As such, work has begun on a completely Ember CLIified branch [here](https://github.com/sir-dunxalot/ember-easy-form-extensions/tree/ember-1.11) - -The `ember-1.11` branch is an evolved easy form API. It is very early stage and undocumented but no longer requires vendor files either. A release will come soon but feel free to dig into the addon tree's source in the meantime. - -```json -devDepencencies: { - "ember-easy-form-extensions": "sir-dunxalot/ember-easy-form-extensions#ember-1.11", -} -``` +Ember apps running 1.12 or below may behave unexpectedly. ## Installation -Uninstall any references to `ember-easy-form` and `ember-validations`. Then: +Uninstall any references to `ember-easy-form` and `ember-validations`and then: -``` +```sh ember install ember-easy-form-extensions ``` @@ -28,151 +19,51 @@ ember install ember-easy-form-extensions `ember-easy-form-extensions` comes prepackaged with `ember-easy-form` and `ember-validations` so you can now build awesome forms and handle the subsequent submission events just as easily as Easy Form makes writing your templates. -The below code works out of the box but is also very customizable and extendible. +Here's an example: ```hbs {{!--app-name/templates/posts/new.hbs--}} {{#form-wrapper}} {{#form-controls legend='Write a new post'}} - {{input title}} - {{input description as='text'}} - {{/form-controls}} - {{form-submission}} -{{/form-wrapper}} -``` - -```js -// app-name/views/posts/new.js + {{!--model.title--}} + {{input-group property='title'}} -import Ember from 'ember'; -import Submitting from 'ember-easy-form-extensions/mixins/views/submitting'; + {{!--model.description--}} + {{input-group property='description' type='textarea'}} -export default Ember.View.extend( - Submitting, { + {{/form-controls}} -}); + {{!--Submit and cancel buttons--}} + {{form-submission}} +{{/form-wrapper}} ``` ```js // app-name/controllers/posts/new.js import Ember from 'ember'; -import Saving from 'ember-easy-form-extensions/mixins/controllers/saving'; +import FormMixin from 'ember-easy-form-extensions/mixins/controllers/form'; -export default Ember.ObjectController.extend( - Saving, { +export default Ember.Controller.extend( + FormMixin, { - // Validations run out of the box validations: { - title: { + 'model.title': { presence: true } } - cancel: function() { - this.transitionTo('posts'); - }, - - save: function() { - // Validations have already been run by the Saving mixin - this.get('content').save().then(function(post) { - this.transitionTo('post', post); - }); - }, - -}); -``` - -# Documentation - -- [Mixins](#mixins) -- [Components](#components) -- [Templating](#templating) - -## Mixins - -The core functionality added by `ember-easy-form-extensions` lies in it's mixins. The mixins handle form submission events and work with the included components to make validating, saving, deleting, and cancelling, a breeze. - -In most situations you will add the `Saving` mixin to your controller, the `Submitting` mixin to your view, and either `Rollback` or `DeleteRecord` to your route. - -### Form Submitting (for views) - -The form submitting mixin is intended to be mixed into **views** to handle `cancel`, `save`, and `destroy` (aka delete) events. This mixin works in parallel with the included [components](#components). - -If you don't specify custom event handlers, the events will be routed directly to the controller. - -This mixin also takes care of hiding buttons after submission to enhance the usability of your forms. - -```js -// app-name/views/posts/new.js - -import Ember from 'ember'; -import Submitting from 'ember-easy-form-extensions/mixins/views/submitting'; - -export default Ember.View.extend( - Submitting, { - -}); -``` - -If you want to add custom handling for the events, you can add `submitHandler()`, `cancelHandler()`, and `destroyHandler()` to your view to handle the respective events. **Each handler should return a promise.** - -```js -// app-name/views/posts/new.js - -import Ember from 'ember'; -import Submitting from 'ember-easy-form-extensions/mixins/views/submitting'; - -export default Ember.View.extend( - Submitting, { - - submitHandler: function() { - return new Ember.RSVP.Promise(function(resolve, reject) { - // Do something unusual here, then resolve. - - this.showCoolAnimation(); - - if (!this.get('someViewProperty')) { - reject(); // Resets the form submission state - } else { - resolve(); // Will call the controller method - } - }); - } - -}); -``` - -### Form Saving (for controllers) - -The form saving mixin is intended to be mixed into **controllers**. Once added, the events handled in your view will automatically validate your model against the controller's validations object (powered by [ember-validations](https://github.com/dockyard/ember-validations)). - -In most use cases, you should add a `save()` and `cancel()` method to the controller: - -```js -// app-name/controllers/posts/new.js - -import Ember from 'ember'; -import Saving from 'ember-easy-form-extensions/mixins/controllers/saving'; - -export default Ember.ObjectController.extend( - Saving, { - - // Validations run out of the box - validations: { - title: { - presence: true - } - }, + /* Runs if cancel button in {{form-submission}} is clicked */ cancel: function() { this.transitionTo('posts'); }, + /* Runs after validations pass and submit button in {{form-submission}} is clicked */ + save: function() { - // Validations have already been run by the Saving mixin this.get('content').save().then(function(post) { this.transitionTo('post', post); }); @@ -181,276 +72,6 @@ export default Ember.ObjectController.extend( }); ``` -The saving mixin will handle all internals including the state of the form (submitted or not submitted) and running the validations - you just have to specify what you want to happen when validations have been run. - -You can also add a destroy method: - -```js -// app-name/controllers/post/edit.js - -import Ember from 'ember'; -import Saving from 'ember-easy-form-extensions/mixins/controllers/saving'; - -export default Ember.ObjectController.extend( - Saving, { - - destroy: function() { - var _this = this; - - // Runs when the user clicks on the destroy submission component after the view has handled the destroy action and checked to see if you've specified a destroyHandler in the view - _this.get('content').destroyRecord().then(function() { - _this.transitionToRoute('posts'); - }); - } - -}); -``` - -Please note, this is best used when you're deleting a persisted model, not a new one - in the latter situation consider using [the delete record mixin](#delete-record). - -The `Saving` mixin also provides support for automatically revalidating your model when you're using a computed property with `ember-validations`. Just add the computed property names to the `revalidateFor` array: - -```js -// app-name/controllers/posts/new.js - -import Ember from 'ember'; -import Saving from 'ember-easy-form-extensions/mixins/controllers/saving'; - -export default Ember.ObjectController.extend( - Saving, { - - revalidateFor: ['required'], - - // Validations run out of the box - validations: { - title: { - presence: { - if: 'required' - } - } - }, - - required: function() { - return this.get('somethingElse') && !this.get('anotherThing'); - }.property('somethingElse', 'anotherThing'), - - cancel: function() {}, - save: function() {}, - -}); -``` - -If your routes follow a RESTful naming convention, you can take advantage of two new **boolean** properties on the controller: -- `newModel` - True if the route is for a new model (e.g. `this.route('new')`) -- `editingModel` - True if the route is for editing a model (e.g. `this.route('edit')`) - -You can use these to set the button text, for example: - -```js -// app-name/controllers/posts/new.js - -import Ember from 'ember'; -import Saving from 'ember-easy-form-extensions/mixins/controllers/saving'; - -export default Ember.ObjectController.extend( - Saving, { - - saveButtonText: function() { - return this.get('editingModel') ? 'Save' : 'Add post'; - }.property('editing'), -}); -``` - -The `saveButtonText` could then be used in your [`{{form-submission}}` component](#form-submission). - -### Rollback (for routes) - -The rollback mixin is intended for use in routes where you are **editing** a model. This mixin will check to see if the model is dirty and will automatically rollback it's changes if it is. The most common reason for this to happen is the user navigates to the edit route of a resource and then clicks cancel. - -```js -// app-name/routes/post/edit.js - -import Ember from 'ember'; -import Rollback from 'ember-easy-form-extensions/mixins/routes/rollback'; - -export default Ember.Route.extend( - Rollback, { - - model: function(params) { - return this.modelFor('post'); - } - -}); -``` - -### Delete Record (for routes) - -The delete record is intended for use in routes where you are creating a **new** record. This mixin will check to see if the model is dirty and will automatically rollback it's changes if it is. The most common reason for this to happen is the user navigates to the new route of a resource and then clicks cancel. - -```js -// app-name/routes/posts/new.js - -import Ember from 'ember'; -import DeleteRecord from 'ember-easy-form-extensions/mixins/routes/delete-record'; - -export default Ember.Route.extend( - DeleteRecord, { - - model: function() { - return this.store.createRecord('post'); - } - -}); -``` - -## Components - -To extend the class of any components just import them from this addon and then export them in your app. For example: - -```js -// app-name/components/form-submissison.js - -import FormSubmissionComponent from 'ember-easy-form-extensions/components/form-submission'; - -export default FormSubmissionComponent.extend({ - // Your functionality here - className: ['buttons-group'] - classNames: ['form_submission'] -}); -``` - -### Form Wrapper - -The `{{#form-wrapper}}` component wraps your code in a `