Skip to content

Instantly share code, notes, and snippets.

@jasonmit
Last active August 22, 2016 16:18
Show Gist options
  • Save jasonmit/bfc059b975fd65363a40f79f45b19b44 to your computer and use it in GitHub Desktop.
Save jasonmit/bfc059b975fd65363a40f79f45b19b44 to your computer and use it in GitHub Desktop.
x-form
export default Service.extend({
i18n: service(),
init() {
this._super(...arguments);
this._subscribers = A();
this.subscribe((e) => logger.error(e), this);
}
subscribe(cb, target) {
this._subscribers.addObject({ cb, target });
},
notifySubscribers(e) {
this._subscribers.forEach({ cb, target = undefined } => {
cb.call(target, e);
});
},
handle(e, fallback) {
this.notifySubscribers(e);
let i18n = get(this, 'i18n');
if (e instanceof Error && i18n.exists(e.message)) {
return i18n.t(e.message);
}
return i18n.t(fallback || 'unknown_error');
}
});
export default Route.extend({
actions: {
handleSubmit(model) {
return model.save().catch(e => {
if (e.status && e.status !== 200) {
throw new Error('failed_request_error');
}
throw e;
});
}
},
model() {
return get(this, 'store').createRecord('sign-up');
}
});
{{#x-form model onSubmit=(action 'handleSubmit') as |f|}}
{{#if f.error}}
{{!-- server error flash placeholder, not for client-side validation --}}
<div class="alert alert--state-error">
{{f.error}}
</div>
{{/if}}
{{!-- f.input also handles client side validation notification --}}
{{f.input name='username' label=(t 'label.username')}}
{{f.input name='password' type='password' label=(t 'label.password')}}
{{f.input name='passwordAgain' type='password' label=(t 'label.password')}}
{{f.submit}}
{{/x-form}}
export default Component.extend({
errorService: service('form-error-handler'),
error: null,
taskRan: false,
submitTask: task(function * () {
let model = get(this, 'model');
let service = get(this, 'errorService');
set(this, 'error', null);
set(this, 'taskRan', true);
try {
let results = null;
if (model && model.validate) {
results = yield model.validate();
}
if (!results || get(results, 'validations.isValid')) {
yield this.attrs.onSubmit(model);
}
} catch(e) {
// service.handle logs the error and converts it into
// a translation if it's an IntlError, otherwise will return the fallback
set(this, 'error', service.handle(e, 'unknown_signup_error'));
// TODO: Promise.reject task?
}
})
});
<form {{action (perform submitTask) on='submit'}} novalidate>
{{yield
(hash
error=error
inFlight=submitTask.isRunning
input=(component 'x-input' showValidation=taskRan model=model disabled=submitTask.isRunning)
submit=(component 'x-submit' showValidation=taskRan disabled=submitTask.isRunning)
)
}}
</form>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment