How do I define an input using Angle Brackets? - ember.js

I know how to make an input in Ember using curly braces:
{{input type="text" value=userInput}}
How do I do this using Angle Brackets component syntax?

<Input #type="text" #value={{#parentVal}} />
or
<Input #type="text" #value={{this.localVal}} />
are the Angle Bracket equivalent to {{input type="text" value=userInput}}.
In versions early in 3.x series, you don't need the # or this in front of the value attribute. # means the argument comes from the parent context, like a parent component or controller, while this. refers to a property that belongs to that component itself.
Angle brackets syntax for inputs was proposed in RFC 459 and released in version 3.10. If you are trying to convert existing hbs to Angle Brackets, check out the syntax conversion guide and check for codemods.

Related

make an input field required in ember.js

I know there is a way in plain html to require the field have some kind of value. I believe it's 'input required'.
However, I'm not sure how to accomplish this in ember using handlebars. I've tried this but it was unsuccessful:
{{input required value=tax class="form-control" placeholder="State Tax"}}
Thanks in advance.
In ember input helpers you always have to give values to attributes. The shourtcuts like <input disabled required value="..."/> in html without value are not allowed in handlebars. Instead you have to write {{input disabled=true required=true value="..."/>
See ember twiddle with your example: https://ember-twiddle.com/b073b4551065e8884056de55fe0c9800?openFiles=templates.application.hbs%2C

How to pass parameters/attributes to a component in EmberJs when using "as" operator

I have a structure to invoke my component in this way, in a .hbs file
{{#myComponent as |section|}}
{{#if (eq section "section1")}}
this is the content for the first section <br>
{{else if (eq section "section2")}}
Some content for section two <br>
More content for second section <br>
{{/if}}
{{/myComponent}}
I want to be able to pass some parameters along, like this
{{#myComponent as |section| param1="xyz" param2=true}}
It is resulting in a parse error while build.
How can i still pass parameters to be accessed by the component in this scenario?
Thanks in advance!!
Figured that the entire component object has to be used, and then the "as" key word follows. Like this
{{#myComponent param1="xyz" param2=true as |section|}}

Input validation with pattern Angular 2

I'm currently writing a simple form in ionic 2 (Angular 2). I was wondering how I'd add a simple regular expression pattern to the validation:
I basically have this:
<form>
<ion-input stacked-label>
<ion-label>{{label.msisdn}}</ion-label>
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
pattern="06([0-9]{8})"
#msisdnForm="ngForm"
>
</ion-input>
<button [disabled]="!msisdnForm.valid" block (click)="requestActivationCode()">
{{label.requestActivationCode}}
</button>
</form>
The maxlength, minlength & required are being picked up (the button is disabled if conditions not met). Now I want to limit the input to numeric and prefix it with 06 (Dutch phone number with minimum amount of numbers).
The pattern is however not picked up in the validation. Can I do it this way, or do I need a code approach?
Add the pattern to a variable
var pattern=/06([0-9]{8})/;
and bind the attribute to it
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
[pattern]="pattern"
#msisdnForm="ngForm"
>
Seems this PR https://github.com/angular/angular/pull/6623/files needs to land first.
There is still an open issue https://github.com/angular/angular/issues/7595
This prevents pattern being bound to. The pattern needs to be statically added to the DOM (without binding) to work.
I put more details (Angular 2.0.8 - 3 March 2016):
https://github.com/angular/angular/commit/38cb526
Example from repo:
<input [ngControl]="fullName" pattern="[a-zA-Z ]*">
I tested it, and it worked :) - here is my code:
<form (ngSubmit)="onSubmit(room)" #roomForm='ngForm' >
...
<input
id='room-capacity'
type="text"
class="form-control"
[(ngModel)]='room.capacity'
ngControl="capacity"
required
pattern="[0-9]+"
#capacity='ngForm'>
UPDATE September 2017
I just wanna to say that currently when I have more experience, I usally use following 'cheap' approach to data validation:
Validation is ONLY on server side (not in angular at all!) and if something is wrong then server (Restful API) return some error code e.g HTTP 400 and following json object in response body (which in angular I put to err variable ):
this.err = {
"capacity" : "too_small"
"filed_name" : "error_name",
"field2_name" : "other_error_name",
...
}
(if server return validation error in different format then you can usually easily map it to above structure)
In html template i use separate tag (div/span/small etc.)
<input [(ngModel)]='room.capacity' ...>
<small *ngIf="err.capacity" ...>{{ translate(err.capacity) }}</small>
As you see, when there is some error in 'capacity' then tag with error translation (to user language) will be visible. This approach have following advantages:
it is very simple
in angular we not double validation code which is (and must be) in server (in case of regexp validation this can either prevent or complicate ReDoS attacks)
we have full control on way the error will be shown to user (here as egzample in <small> tag)
because in server response we return error_name (instead of direct error message), we can easily change error message (or translate it) by modify only frontend-angular code (or files with translations). So in that case we not need to touch backend/server code.
Of course sometimes (if this is needed - eg. retypePassword field which is never send to server) I make exceptions of above approach and make some validation in angular (but use similar "this.err" mechanism to show errors (so I not use pattern attribute directly in input tag but rather I make regexp validation in some component method after user raise proper event like input-change or save) .

How to change input helper's class based on some condition in Ember

How can the if condition clause be used in an input helper.
I tried:
{{input class="{{if errors.name "style-error"}}" }}
It caused building error.
the errors.name here is property from controller.
I reckon that it is the nested double curly braces causing the syntax error, but don't know how to achieve this conditional class declaration.
You can nest helpers using parenthesis:
{{input class=(if errors.name "style-error")}}
You should use this instead of the xxxBinding="..." syntax
You can use the concat helper to conditionally add multiple classes:
Conditionally add static + dynamic class:
{{input class=(if errors.name (concat "static-class " dynamicClass))}}
Conditionally add two dynamic classes:
{{input class=(if errors.name (concat dynamicClass1 " " dynamicClass2))}}
Add one class if the condition is true, another if it's false:
{{input class=(if errors.name "style-error" "style-success")}}
Add a class only when the condition is false:
{{input class=(unless errors.name "style-success")}}
Two conditions:
{{input class=(concat (if errors.name "name-error") " " (if errors.date "date-error"))}}
For more complex boolean arithmetic (e.g. and/or/not, equality and comparisons) you can use ember-truth-helpers
Since input is an Ember helper here and not an HTML element use classBinding -
{{input classBinding="errors.name:style-error"}}
classBinding takes a space-separated list of arguments in the format of <condition>:<class if true>:<class if false>. So in this case style-error will be applied when errors.name evaluates to true (ie the key exists on the hash).
Its the same syntax as bind-attr. Also, :<class> works, and <condition>::<class if false>. See the docs here.
Note that classBinding is currently supported (discussion here), but it is expected to be deprecated sometime before 3.0 (with appropriate deprecation warnings) with the introduction of angle bracket components.

how to set two class name for Ember.js input helper

i'm trying to bind an input element like this:
{{input value=email type="text" placeholder="Enter email" class=emailError:with-error}}
it works just fine, as long as I try to assign it only 1 class name ".with-error".
how can I assign 2 class names, so it will be: ".with-error .second-class"?
I know how to do it with:
{{bind-attr class=":secondClass emailError:with-error"}}
but this doesn't work with input helper.
Thanks!
This feature is not well documented, but when defining attributes on a Handlebars helper, you can either leave out the quotes to indicate that you want the value of the attribute to be a bound variable, or you can add the suffix "Binding" and then use quotes with an expression similar to the one you would use with {{bind-attr}}.
So, in your case, the following should work:
{{input value=email type="text" placeholder="Enter email" classBinding="emailError:with-error :myClassName"}}
Note how instead of class=myBoundValues we are using classBinding="myBoundValue".