Skip to content

Commit

Permalink
feat(edit-form): add a minimalistic form for editing model fields
Browse files Browse the repository at this point in the history
  • Loading branch information
velrest committed Oct 14, 2020
1 parent 373f213 commit 31e4a99
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 0 deletions.
40 changes: 40 additions & 0 deletions addon/components/edit-form.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<form
class="uk-form-stacked"
{{did-insert (set this.form)}}
{{on "submit" (perform this.save)}}
>
{{yield}}

<div class="uk-flex uk-flex-right uk-margin">
{{! without quotes on the @route the LinkTo component tries to set the property listViewRouteName which has no setter}}
<LinkTo
@route="{{this.listViewRouteName}}"
class="uk-button uk-button-default uk-margin-right"
data-test-back
>
{{t "emeis.form.back"}}
</LinkTo>

{{#unless @noDelete}}
<UkButton
@loading={{this.delete.isRunning}}
@disabled={{this.delete.isRunning}}
class="uk-margin-right uk-button-danger"
data-test-delete
{{on "click" (perform this.delete)}}
>
{{t "emeis.form.delete"}}
</UkButton>
{{/unless}}

<UkButton
@loading={{this.save.isRunning}}
@disabled={{this.save.isRunning}}
@color="primary"
@type="submit"
data-test-save
>
{{t "emeis.form.save"}}
</UkButton>
</div>
</form>
51 changes: 51 additions & 0 deletions addon/components/edit-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { inject as service } from "@ember/service";
import Component from "@glimmer/component";
import { task } from "ember-concurrency-decorators";

import handleModelErrors from "ember-emeis/decorators/handle-model-errors";

export default class EditFormComponent extends Component {
@service intl;
@service notification;
@service router;

get parentRouteName() {
return this.router.currentRoute.parent.name;
}

get listViewRouteName() {
return (
this.args.listViewRouteName ||
`${this.parentRouteName}.index`.replace("ember-emeis.", "")
);
}

@task
*save(event) {
try {
event.preventDefault();

const model = this.args.updateModel(this.args.model, this.form.elements);
const isNew = model.isNew;

yield model.save();

this.notification.success(this.intl.t("emeis.form.save-success"));

if (isNew) {
this.router.replaceWith(`${this.parentRouteName}.edit`, model);
}
} catch (exception) {
this.notification.danger(this.intl.t("emeis.form.save-error"));
}
}

@task
@handleModelErrors({ errorMessage: "emeis.form.delete-error" })
*delete() {
yield this.args.model.destroyRecord();
this.notification.success(this.intl.t("emeis.form.delete-success"));
// I dont really understand why this replaceWith needs the "ember-emeis." prefix and the onw in save does not :/.
this.router.replaceWith(`ember-emeis.${this.listViewRouteName}`);
}
}
9 changes: 9 additions & 0 deletions addon/components/edit-form/element.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">
{{@label}}
</label>
<div class="uk-form-controls">
{{yield}}

</div>
</div>
1 change: 1 addition & 0 deletions app/components/edit-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/components/edit-form";
1 change: 1 addition & 0 deletions app/components/edit-form/element.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/components/edit-form/element";
103 changes: 103 additions & 0 deletions tests/integration/components/edit-form-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { render, click } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { setupRenderingTest } from "ember-qunit";
import { module, test } from "qunit";

module("Integration | Component | edit-form", function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
const router = class {
replaceWith() {}
hasRoute() {}
transitionTo() {}
_doTransition() {}
generateURL() {}
currentRoute = {
parent: {
name: "ember-emeis.parent-route",
},
};
};
this.router = new router();
this.owner.register("service:router", this.router, { instantiate: false });
this.owner.register("service:-routing", this.router, {
instantiate: false,
});
this.owner.register("router:main", this.router, { instantiate: false });
});

hooks.afterEach(function () {
delete this.router;
});

test("noDelete", async function (assert) {
assert.expect(3);

await render(hbs`<EditForm @noDelete="true"/>`);

assert.dom("[data-test-back]").exists();
assert.dom("[data-test-delete]").doesNotExist();
assert.dom("[data-test-save]").exists();
});

test("back", async function (assert) {
assert.expect(1);
this.router.transitionTo = (route) => {
assert.equal(route, "parent-route.index");
};

await render(hbs`<EditForm />`);

await click("[data-test-back]");
});

test("delete", async function (assert) {
assert.expect(3);
this.router.replaceWith = (route) => {
assert.equal(route, "ember-emeis.parent-route.index");
};

this.set("model", {
destroyRecord() {
assert.step("destroyRecord");
},
});

await render(hbs`<EditForm @model={{this.model}}/>`);

await click("[data-test-delete]");
assert.verifySteps(["destroyRecord"]);
});

test("save", async function (assert) {
assert.expect(7);
this.router.replaceWith = (route) => {
assert.equal(route, "ember-emeis.parent-route.edit");
assert.step("replaceWith");
};

this.setProperties({
model: {
save() {
assert.step("save");
},
isNew: true,
},
updateModel(model, elements) {
assert.ok(elements.test, "Test that test input is passed");
assert.ok(model, "Test if model is truthy");
assert.step("updateModel");
return model;
},
});

await render(hbs`
<EditForm @model={{this.model}} @updateModel={{this.updateModel}}>
<input name="test">
</EditForm>
`);

await click("[data-test-save]");
assert.verifySteps(["updateModel", "save", "replaceWith"]);
});
});
21 changes: 21 additions & 0 deletions tests/integration/components/edit-form/element-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { setupRenderingTest } from "ember-qunit";
import { module, test } from "qunit";

module("Integration | Component | edit-form/element", function (hooks) {
setupRenderingTest(hooks);

test("it renders", async function (assert) {
this.set("label", "Hey");

await render(hbs`
<EditForm::Element @label={{this.label}}>
Text
</EditForm::Element>
`);

assert.dom("label").hasText(this.label);
assert.dom(".uk-form-controls").hasText("Text");
});
});

0 comments on commit 31e4a99

Please sign in to comment.