Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom label components. #95

Merged
merged 1 commit into from
Apr 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,30 @@ There are three integration points for custom components:
* update the model's value with `fi.update`
* mark your component as dirty with `fi.setDirty`


### Custom label components
If you want to have a label on your input which renders something non-standard (for instance tooltips),
then you can pass your custom component to the input in the following manner:
```Handlebars
{{!-- custom-label --}}
<label style="color: green;" for={{inputId}} class={{config.css.label}}>
{{labelText}}
</label>
```
```Handlebars
{{f.input labelComponent=(component "custom-label" labelText="Custom Label")}}
```
*Note:* When adding a custom component for input of type checkbox, one has to add `{{yield}}` inside the label.
This is because, this kind of input renders inside a label tag.
```Handlebars
{{!-- checkbox-label --}}
<label style="color: green;">
{{yield}}
{{label}}
</label>
```


## Buttons

`{{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:
Expand Down
6 changes: 2 additions & 4 deletions addon/components/validated-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export default Component.extend({

dirty: false,

labelComponent: 'validated-label',

required: false,

type: 'text',
Expand Down Expand Up @@ -61,10 +63,6 @@ export default Component.extend({
return false;
}),

requiredLabel: computed('config', function() {
return this.get('config.label.required') || '*';
}),

_val: computed('value', 'model', 'name', function() {
return this.get('value') || this.get(`model.${this.get('name')}`);
}),
Expand Down
27 changes: 27 additions & 0 deletions addon/components/validated-label.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Component from '@ember/component';
import { computed } from '@ember/object';
import layout from '../templates/components/validated-label';

/**
* This component generates default labels.
*
* It will be used when label parameter is specified.
* {{validated-input label="Name default"}} (Will render label next to input field.)
*
* or it is possible to override it with a custom component:
* {{validated-input label="Name custom"
* labelComponent=(component "some-custom-component" customComponentParam="Custom text for custom component.")}}
*/
export default Component.extend({
layout,

tagName: 'label',

attributeBindings: ['inputId:for'],

classNameBindings: ['config.css.label'],

requiredLabel: computed('config', function() {
return this.get('config.label.required') || '*';
}),
});
24 changes: 11 additions & 13 deletions addon/templates/components/validated-input.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{{#if (not-eq type "checkbox")}}
{{#if label}}
<label class={{config.css.label}} for={{inputId}}>
{{label}}{{#if required}} {{requiredLabel}}{{/if}}
</label>
{{#if (or label (not-eq labelComponent 'validated-label'))}}
{{component labelComponent label=label config=config inputId=inputId required=required}}
{{/if}}
{{/if}}

Expand Down Expand Up @@ -74,16 +72,16 @@

{{else if (eq type "checkbox")}}
<div class="{{config.css.checkbox}}">
<label>
{{#component labelComponent label=label config=config inputId=inputId required=required}}
<input
type = "checkbox"
name = {{name}}
disabled = {{disabled}}
checked = {{get model name}}
onclick = {{action "update" value = "target.checked"}}
onfocusout = {{action "setDirty"}}>
<span>{{label}}</span>
</label>
type = "checkbox"
name = {{name}}
id = {{inputId}}
disabled = {{disabled}}
checked = {{get model name}}
onclick = {{action "update" value = "target.checked"}}
onfocusout = {{action "setDirty"}}>
{{/component}}
</div>

{{else if (eq type "textarea")}}
Expand Down
2 changes: 2 additions & 0 deletions addon/templates/components/validated-label.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{yield}}
{{label}}{{#if required}} {{requiredLabel}}{{/if}}
1 change: 1 addition & 0 deletions app/components/validated-label.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-validated-form/components/validated-label';
4 changes: 4 additions & 0 deletions tests/dummy/app/templates/components/color-label.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<label style="color: green" for={{inputId}} class={{config.css.label}}>
{{yield}}
Custom label component!
</label>
2 changes: 2 additions & 0 deletions tests/dummy/app/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

{{f.input type="checkbox" label="I agree with the terms and conditions" name="terms"}}

{{f.input type="checkbox" name="terms" labelComponent=(component "color-label")}}

{{f.submit label="Save"}}
{{/validated-form}}

Expand Down
67 changes: 67 additions & 0 deletions tests/integration/components/validated-label-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Component from '@ember/component';

moduleForComponent('validated-label', 'Integration | Component | validated label', {
integration: true
});

test('it renders labels', function(assert) {
this.render(hbs`{{validated-input label="Default name" name="default-name"}}`);
assert.ok(this.$('label').text().includes('Default name'));
assert.ok(this.$('label').attr('for').includes('default-name'));
assert.ok(this.$('label').attr('id').includes('ember'));
assert.equal(this.$('label').attr('class'), 'ember-view');
});

test('it renders labels with styles from config', function(assert) {
this.set('config', {
css: {
label: 'control-label'
}
});
this.render(hbs`{{validated-input label="Default name" config=config}}`);
assert.equal(this.$('label').attr('class'), 'control-label ember-view');
});

test('it renders custom label component', function(assert) {
this.register('component:custom-label', Component.extend());
this.register(
'template:components/custom-label',
hbs`<label style="color: green;"></label>`
);
this.render(hbs`{{validated-input labelComponent=(component "custom-label")}}`);
assert.equal(this.$('label').attr('style'), 'color: green;');
});

test('it passes original variables to custom component', function(assert) {
this.set('config', "this would be some config :)");
this.register('component:custom-label', Component.extend());
this.register(
'template:components/custom-label',
hbs`<label style="color: green;"><span id="orig-label">{{label}}</span>
<span id="form-config">{{config}}</span>
<span id="orig-input-id">{{inputId}}</span>
<span id="orig-input-required">{{required}}</span></label>`
);
this.render(
hbs`{{validated-input label="Name custom" name="orig-name"
required=true config=config labelComponent=(component "custom-label")}}`
);
assert.equal(this.$('label').attr('style'), 'color: green;');
assert.equal(this.$('#orig-label').text(), 'Name custom');
assert.equal(this.$('#form-config').text(), 'this would be some config :)');
assert.equal(this.$('#orig-input-required').text(), 'true');
assert.ok(this.$('#orig-input-id').text().includes('input-orig-name'));
});

test('it passes custom variables to custom component', function(assert) {
this.register('component:custom-label', Component.extend());
this.register(
'template:components/custom-label',
hbs`<label style="color: green;">{{customVariable}}</label>`
);
this.render(hbs`{{validated-input labelComponent=(component "custom-label" customVariable="Awesome!")}}`);
assert.equal(this.$('label').attr('style'), 'color: green;');
assert.equal(this.$('label').text(), 'Awesome!');
});