Skip to content

Commit

Permalink
feat(validated-button): yield customizable button
Browse files Browse the repository at this point in the history
  • Loading branch information
derrabauke committed Dec 22, 2021
1 parent a83c7bf commit 30d9c27
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 138 deletions.
6 changes: 3 additions & 3 deletions addon/components/validated-button.hbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{{#let
(component
this.buttonComponent
onClick=@action
loading=@loading
disabled=@disabled
onClick=this.click
loading=this.loading
disabled=(or @disabled this.loading)
label=@label
type=@type
)
Expand Down
48 changes: 48 additions & 0 deletions addon/components/validated-button.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,55 @@
import { action } from "@ember/object";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { resolve } from "rsvp";

import themedComponent from "../-private/themed-component";

const ON_CLICK = "on-click";
const ON_INVALID_CLICK = "on-invalid-click";
export default class ValidatedButtonComponent extends Component {
@themedComponent("validated-button/button") buttonComponent;

@tracked _loading;

get loading() {
return this.args.loading || this._loading;
}

@action
async click(event) {
// handle only clicks for custom buttons
// everything else is handled by the validated form itself
if (this.args.type !== "button") {
return this.args.action(event);
}

event.preventDefault();
const model = this.args.model;

if (!model || !model.validate) {
this.runCallback(ON_CLICK);
return;
}

await model.validate();

if (model.get("isInvalid")) {
this.runCallback(ON_INVALID_CLICK);
} else {
this.runCallback(ON_CLICK);
}
}

runCallback(callbackProp) {
const callback = this.args[callbackProp];
if (typeof callback !== "function") {
return;
}

this._loading = true;
resolve(callback(this.args.model)).finally(() => {
this._loading = false;
});
}
}
7 changes: 7 additions & 0 deletions addon/components/validated-form.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
label="Save"
action=this.submit
)
button=(component
"validated-button"
type="button"
loading=this.loading
label="Action"
model=@model
)
)
}}
</form>
2 changes: 1 addition & 1 deletion addon/components/validated-input/types/checkbox-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Component from "@glimmer/component";

export default class CheckboxGroupComponent extends Component {
@action
onUpdate(event, key) {
onUpdate(key, event) {
event.preventDefault();

const value = this.value || [];
Expand Down
48 changes: 39 additions & 9 deletions tests/dummy/app/templates/docs/components/validated-button.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
# Validated button

`{{validated-form}}` also yields a submit button component that can be
accessed with `{{f.submit}}`. You can also use it as a block style component
`{{#f.submit}}Test{{/f.submit}}` if you don't want to pass the label as a
property. It takes the following properties:
`{{validated-form}}` yields two kinds of button components:
- `{{f.submit}}`: a submit button for the form
- `{{f.button}}`: a customizable button without HTML-form specific functionality.

**label `<String>`**
You can use them as a block style component `{{#f.submit}}Test{{/f.submit}}` if you don't want to pass the label as a
property.

Both take the following properties:

**label `<String>`**
The label of the form button.

**type `<String>`**
Type of the button. Default: `button`.
**type `<String>`**
Type of the button. Default for submit: `submit` and for standard button: `button`.
*Watch out:* If you define `type=submit` then the `on-submit` handler of the form will be triggered.

**disabled `<Boolean>`**
**disabled `<Boolean>`**
Specifies if the button is disabled.

**loading `<Boolean>`**
**loading `<Boolean>`**
Specifies if the button is loading. Default: Automatic integration of `ember-concurrency`.

<!-- prettier-ignore-start -->
Expand All @@ -30,3 +35,28 @@ Specifies if the button is loading. Default: Automatic integration of `ember-con
{{demo.snippet 'button-template.hbs'}}
{{/docs-demo}}
<!-- prettier-ignore-end -->


Further you can leverage the `{{f.button}}` component for custom actions. The model of the wrapping form component will get passed to the on-click handler as first argument.

Passing a custom on click function is possible on the `{{f.buttton}}` via:

**on-click `<Function>`**
Passes an on-click function to the button component.

**on-invalid-click `<Function>`**
Passes a function which is triggered after clicking on the button and when the validation proved the contents to be invalid.

<!-- prettier-ignore-start -->
{{#docs-demo as |demo|}}
{{#demo.example name='button-advanced-template.hbs'}}
{{#validated-form as |f|}}
{{f.button label='Custom action' on-click=(action (mut triggered) true)}}
{{#f.button on-click=(action (mut triggered) true)}}Custom action button in block style...{{/f.button}}
{{if triggered 'Action triggered!'}}
{{/validated-form}}
{{/demo.example}}

{{demo.snippet 'button-advanced-template.hbs'}}
{{/docs-demo}}
<!-- prettier-ignore-end -->
Loading

0 comments on commit 30d9c27

Please sign in to comment.