Is it possible to set default property to components in ember.js? - ember.js

I have a simple component that looks like this:
<script type="text/x-handlebars" id="components/Gd-text-input">
<label {{bind-attr for="name"}}>
{{label}}
</label>
<input type="text" {{bind-attr name="key" id="name"}} />
</script>
I would like to add the attribute type to the input field, and if no type is passed when including the component, like this for example:
{{Gd-text-input label="First Name" name="firstname" key="entry.810220554" }}
I would like it to default to type="text". How would I go about doing this?

Yep, you can subclass Ember.Component:
YourApp.GdTextInputComponent = Ember.Component.extend({
type: 'text'
});

Related

data-value attribute in emberjs

I want to add data-value attribute in input element:
{{input type="text" data-value=ec.ec_id value=ec.ecl_subject placeholder=ec.ecl_en_subject name="ecl_subject" class="form-control" }}
But its not visible in browser:
<input id="ember874" class="ember-view ember-text-field form-control" placeholder="Doctor4US: Appointment" type="text" name="ecl_subject">
ADDING DATA ATTRIBUTES
By default, view helpers do not accept data attributes
i.e.
{{input type="text" data-value=ec.ec_id value=ec.ecl_subject name="ecl_subject" }}
Render as
<input id="ember257" class="ember-view ember-text-field" type="text" value="12">
There are two ways to enable support for data attributes. One way
would be to add an attribute binding on the view, e.g. Ember.TextField for the specific attribute:
Ember.TextField.reopen({
attributeBindings: ['data-value']
});
Now the same handlebars code above renders the following HTML:
<input id="ember259" class="ember-view ember-text-field"
type="text" data-value="110" value="12">
You can also automatically bind data attributes on the base view with the following:
Ember.View.reopen({
init: function() {
this._super();
var self = this;
// bind attributes beginning with 'data-'
Em.keys(this).forEach(function(key) {
if (key.substr(0, 5) === 'data-') {
self.get('attributeBindings').pushObject(key);
}
});
}
});
For more detail reffer:https://guides.emberjs.com/v1.10.0/templates/binding-element-attributes/
Ember Input helpers doesn't allow data-attributes. The list of allowed attributes can be found at https://guides.emberjs.com/v2.6.0/templates/input-helpers/
The solution for problem is that you use html tag itself, when you want to place data-attributes like below
<input type="text" data-value="{{ec.ec_id}}" value="{{ec.ecl_subject}}" placeholder="{{ec.ecl_en_subject}}" name="ecl_subject" class="form-control/>

Ember.js: conditional input attribute

In Ember's input helper, how can I show/hide attributes based on a condition? For example, let's say I want to show required="required" if isEditable is true and disabled="disabled" otherwise. Currently I have something like this:
{{#if isEditable}}
{{input value=model.name required="required"}}
{{else}}
{{input value=model.name disabled="disabled"}}
{{/if}}
...but it would be nice if I bind the attributes somehow instead.
{{ input type='text' required=required disabled=disabled }} works just fine
Working example here
There are a whole bunch of attributes that you can bind directly and required and disabled are among the pack. See here
Note #blackmind is correct that if you were to do this from scratch, you would need to do some work. Fortunately though, TextSupport already does the work for you... :) See here
From the EmberJS site
By default, view helpers do not accept data attributes. For example
{{#link-to "photos" data-toggle="dropdown"}}Photos{{/link-to}}
{{input type="text" data-toggle="tooltip" data-placement="bottom" title="Name"}}
renders the following HTML:
<a id="ember239" class="ember-view" href="#/photos">Photos</a>
<input id="ember257" class="ember-view ember-text-field" type="text" title="Name">
There are two ways to enable support for data attributes. One way would be to add an attribute binding on the view, e.g. Ember.LinkView or Ember.TextField for the specific attribute:
Ember.LinkView.reopen({
attributeBindings: ['data-toggle']
});
Ember.TextField.reopen({
attributeBindings: ['data-toggle', 'data-placement']
});
Now the same handlebars code above renders the following HTML:
<a id="ember240" class="ember-view" href="#/photos" data-toggle="dropdown">Photos</a>
<input id="ember259" class="ember-view ember-text-field"
type="text" data-toggle="tooltip" data-placement="bottom" title="Name">
Or you can reopen the view
Ember.View.reopen({
init: function() {
this._super();
var self = this;
// bind attributes beginning with 'data-'
Em.keys(this).forEach(function(key) {
if (key.substr(0, 5) === 'data-') {
self.get('attributeBindings').pushObject(key);
}
});
}
});
I typically do the following
<input type="checkbox" {{bind-attr disabled=isAdministrator}}>

Passing variables to handlebars partials in Ember.js

What I want to do should be fairly simple.
I want to pass variables to partials for reusability.
I want to do something like this :
<form {{action login content on="submit"}}>
<fieldset>
{{partial 'components/field-email' label="Email" fieldname="email" size="full"}}
[...]
</fieldset>
</form>
Instead of doing this :
<form {{action login content on="submit"}}>
<fieldset>
<div {{bind-attr class=":field :email size"}}>
<label {{bind-attr for=fieldname}}>{{label}}</label>
{{input type="email" id=fieldname name=fieldname valueBinding="email" placeholder=label}}
</div>
[...]
</fieldset>
</form>
coming from Rails, I expected this to just work, but it seems I can't (don't know how to) pass variables to a partial. I looked at all the ways to "include a template part":
partial
view
render
The thing that worked for me is using a View. But I thinks it's overkill. I just want separate sub-templates for reusability and readability, no context change or specifying a controller needed here.
Edit:
I also tried to use this partial as a component :
{{field-email type="email" id="email" name="email" valueBinding="email" placeholder=label size="full"}}
Which works for everything except the valueBinding.
I guess it's also worth mentioning that I have a route setup with an action that calls login on my AuthController :
App.LoginRoute = Ember.Route.extend
model: -> Ember.Object.create()
setupController: (controller, model) ->
controller.set 'content', model
controller.set "errorMsg", ""
actions:
login: ->
log.info "Logging in..."
#controllerFor("auth").login #
This whole thing works if all the markup is in the login template but fails if I try to break it up with partials, components and such.
There has to be something that I didn't see...
You should use a component in this case.
If you setup your template correctly (components/field-email), you can use on this way:
{{field-email label="Email" fieldname="email" size="full"}}
You could setup the html component properties, if you define the component. Based on your example, it could be:
App.FieldEmailComponent = Ember.Component.extend({
classNames: ['size'],
classNameBindings: ['email', 'field'],
field: null,
email: null
});
Example: http://emberjs.jsbin.com/hisug/1/edit
Got it working, I had to use a component. I had messed up the "value" part.
components/field-email.hbs :
<div {{bind-attr class=":field :email size"}}>
<label {{bind-attr for=fieldname}}>{{label}}</label>
{{input type="email" name=fieldname value=value placeholder=label}}
</div>
login.hbs :
<form {{action login content on="submit"}}>
<fieldset>
{{field-email label="Email" fieldname="email" value=email size="full"}}
[...]
</fieldset>
</form>
What I get from this is that in order for attributes to be used in a component they have to be explicitly set when using the component. Once they are set, they are bound.
In my case, when the input value changes, the associated route property is updated as well which is pretty cool.

Set Handlebar class on the fly

I'd like to update the class of a div according to the user input. A simple input text that need to be validated.
I have to go with a helper but I can't figure it out.
<div class="{{validationClass}}">
<p>{{input type="text" id="titleInput" value=title placeholder="Title"}}</p>
</div>
When there's nothing written in the text field I'd like to surround the box with the red colour, after the used typed a single character I want it to go default.
So, according to bootstrap 2.x I'd need to set the div class to control-group error or control-group success etc.
I've never created a helper so I'm struggling, I don't know how to call it and how to return the desired string to be replaced in {{validationClass}}
Thanks.
You can use the bind-attr helper .
This is a sample:
<script type="text/x-handlebars" data-template-name="index">
<div {{bind-attr class=":control-group validationClass"}}>
<p>{{input type="text" id="titleInput" value=title placeholder="Title"}}</p>
</div>
</script>
App.IndexController = Ember.ObjectController.extend({
title: null,
validationClass: function() {
var title = this.get('title');
return title ? 'success' : 'error';
}.property('title')
});
http://jsfiddle.net/marciojunior/6Kgty/
Use {{bind-attr}} helper
{{!hbs}}
<div {{bind-attr class=":control-group isError:error"}}>
{{input type="text" class="form-control" value=testVal}}
</div>
//Controller
App.ApplicationController = Em.Controller.extend({
testVal: '',
isError: Em.computed.empty('testVal')
});
Sameple Demo

Extending Em.TextField

I need to make a bootstrap form with 10 textfield elements.
From the bootstrap doc, I need to have this code for each textfield element:
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email">
</div>
</div>
Em.TextField object only manage the
<input type="text...
and I would like to minimize my handlebar form.
What is the best solution to have the expected result with the minimum of code ?
Is there a sample code for this ?
You can create a new view that includes all of the required bootstrap markup and incorporates the built in Ember.TextField input element. The custom TextField has an added label property that sets the text for the form label.
JSBin Example
Custom TextField:
JS:
App.BootstrapTextFieldView = Ember.View.extend({
templateName: 'bootstrapTextField',
inputElement: null
});
Handlebars:
<script type="text/x-handlebars" data-template-name='bootstrapTextField'>
<div class='control-group'>
<label class="control-label" {{bindAttr for='view.inputElement.elementId'}}>{{view.label}}</label>
<div class="controls">
{{view Ember.TextField valueBinding='view.value' viewName="inputElement"}}
</div>
</div>
</script>
Using the new view
You would use it similar to using the normal Ember.TextField:
<form class="form-horizontal">
{{view App.BootstrapTextFieldView valueBinding='textFieldValue' labelBinding='textFieldLabel'}}
</form>
The only tricky part was correctly setting the for='..." property on the <label> since we need to get the auto-generated id of the {{view Ember.TextField ...}}. This can be done by using the viewName property of the {{view ...}} helper. Setting {{view App.theViewHere viewName='desiredViewName' lets us access the instance of Ember.TextField we created and set the for property of the label to the view's id using the {{bindAttr...}} helper.