Angular focus on formcontrol - forms

I have the following input:
<input
#participantInput="ngModel"
id="participantInput"
pattern="^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$"
class="cell small-7"
placeholder="John.Doe#gmail.com"
[(ngModel)]="newParticipantMail"
(keyup.enter)="addParticipant()"
style="height:10%;">
Due to the #participantInput="ngModel"
I'm not able to retrieve the elementRef like :
#ViewChild('participantInput') participantInput: ElementRef;
So, how can I set the focus on that field?

You can add another template variable like this:
<input
#participantInput="ngModel"
#participantRef
id="participantInput"
pattern="^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$"
class="cell small-7"
placeholder="John.Doe#gmail.com"
[(ngModel)]="newParticipantMail"
(keyup.enter)="addParticipant()"
style="height:10%;">
Then you can access it into your component
#ViewChild('participantRef') participantRef: ElementRef;
Obviously you must wait for view initialization, for example implementing AfterViewInit interface

Related

How to simulate ionBlur in tests

Maybe I'll start with what I want to achieve: I have a form with a required field. By default it should not display any error. The error should be displayed if a user touches the field. So my field looks more or less like this:
<ion-input .... (ionBlur)="updateDispayedErrors()"></ion-input>
But I don't know how to test it because:
Running fixture.debugElement.nativeElement.blur() does not triggers ionBlur handler (the same with ....dispatchEvent(new Event('blur')))
Plain angular (blur) does not work (i.e. if I change the code to (blur)="updateDisplayErrors()" then it does not work)
It seems that calling blur() method on native <input .../> element that is created in the browser would work but... the problem is that when I run the tests fixture.debugElement.nativeElement.childNodes is empty... So the native <input .../> is not created
Please let me know if you would like to see a full example to illustrate it.
If you add a selector to ion-input like:
<ion-input .... (ionBlur)="updateDisplayedErrors()" id="specialInput"></ion-input>
Then you can use fixture.debugElement.triggerEventHandler:
import { By } from '#angular/platform-browser';
...
it('should emit ionBlur', () => {
const ionDe = fixture.debugElement.query(By.css('#specialInput'));
const ionBlurResult = spyOn(component, 'updateDisplayedErrors');
ionDe.triggerEventHandler('ionBlur', {});
expect(ionBlurResult).toHaveBeenCalled();
});

TextField is not getting updated on re-render with different intialValues

I'm using redux-form-material-ui for the forms. I have simple form with two text fields. This form will show the initalValues passed to it and user can also update the values of TextField. These TextFields working fine with validations and all but I'm facing problem while re-rendering. On route change, I'm passing the different intialValues to that form component but even though proper values passed to it, TextFields are not getting updated. It just shows the first time passed initialValues.
Here is my code:
From parent component:
<ReduxForm {...initialValues} />
ReduxForm component:
class ReduxForm extends React.Component {
render () {
return (
<div>
<form onSubmit={() => console.log('Submitted')} >
<Field
className='input-field'
name='name'
component={TextField}
floatingLabelText='Full Name'
/>
<Field
className='input-field'
name='email'
component={TextField}
floatingLabelText='Email'
/>
</form>
</div>
)
}
}
export default reduxForm({
form: 'test-form',
validate
})(ReduxForm)
I Know that, this is the same problem with defaultValue in material-ui's TextField. Is this expected behavior in redux-form-material-ui also? If so, is there way I can solve this issue without setting the state and all?
Thank you!
Haven't used redux-form-material-ui but try adding enableReinitialize: true to your reduxForm decorator
export default reduxForm({
form: 'test-form',
validate,
enableReinitialize: true
})(ReduxForm);
And see if that works.

Angular 2 checkbox - How to use [checked] with (ngModelChange)?

I'm having trouble programmatically setting a checkbox in Angular 2. The following code fires onCheck() whenever the user checks the checkbox. I can also check the checkbox programmatically by setting this.select to 'true'.
<input type="checkbox" [(ngModel)]="v.checked" [checked]="select" (ngModelChange)="onCheck(v.checked)">
My problem is that when I set this.select to 'true', ngModelChange doesn't seem to detect the change and onCheck() doesn't fire... :-(
Any tips? Is there an alternative way to programmatically set a checkbox AND have its associated function fire?
you can use checkbox with component variable like :
#Component({
selector : 'my-component'
template : `<input type="checkbox" [(ngModel)]="selected"/>`
})
export class MyComponent(){
public selected: boolean = false;
}

How do I bind a value to a textbox in Angular2?

I have been trying to figure out how to bind a value to a textbox in Angular2. Currently I have a textbox with a placeholder that is loaded with a predetermined value.
<input id="textbox" class="k-textbox" placeholder={{label}} />
But once I change a value of a date component, I would want the placeholder value to be updated to the date value selected. So far i wrote this but this doesn't seem to be working. Please advice.
date-component.html
<input id="datepicker" (input)="changeLabel()"/>
date-component.ts
label:string;
constructor() {
this.label = 'Select Date';
}
changeLabel() {
this.label = 'Date Selected';
}
}
use an click event to propagate the changes.
date-component.html
<input id="datepicker" (click)="changeLabel()"/> //<-- click event
You could use two way databinding with NgModel.
https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
Basically this would make "label" change to whatever the user types.
<input [(ngModel)]="label" id="datepicker" />
You will also need to import FormsModule in your app.
Plunker to show what I mean:
https://plnkr.co/edit/CfmalT7GesrP5lzBsNFx?p=preview
use keyup Event
<input (keyup)="changeLabel()">
enter the value its call the keyup event

Trying to think about how to build a multi step form in angular 2

I am trying to build a small, 3 step form. It would be something similar to this:
The way I did this in react was by using redux to track form completion and rendering the form body markup based on the step number (0, 1, 2).
In angular 2, what would be a good way to do this? Here's what I am attempting at the moment, and I'm still working on it. Is my approach fine? Is there a better way to do it?
I have a parent component <app-form> and I will be nesting inside it <app-form-header> and <app-form-body>.
<app-form>
<app-header [step]="step"></app-header>
<app-body [formData]="formData"></app-body>
</app-form>
In <app-form> component I have a step: number and formData: Array<FormData>. The step is just a index for each object in formData. This will be passed down to the header. formData will be responsible the form data from user. Each time the form input is valid, user can click Next to execute nextStep() to increment the index. Each step has an associated template markup.
Is there a better way to do something like this?
don't overdo it, if it is a simple form you don't need to use the router or a service to pass data between the steps.
something like this will do:
<div class="nav">
</div>
<div id="step1" *ngIf="step === 1">
<form></form>
</div>
<div id="step2" *ngIf="step === 2">
<form></form>
</div>
<div id="step3" *ngIf="step === 3">
<form></form>
</div>
It's still a small template, and you kan keep all of the form and all the data in one component, and if you want to you can replace the ngIf with something that switches css-classes on the step1,2,3 -divs and animate them as the user moves to the next step
If you want to keep things extensible, you could try something like this:
<sign-up>
<create-account
[model]="model"
[hidden]="model.createAccount.finished">
</create-account>
<social-profiles
[model]="model"
[hidden]="model.socialProfiles.finished">
</social-profiles>
<personal-details
[model]="model"
[hidden]="model.personalDetails.finished">
</personal-details>
</sign-up>
export class SignUpVm {
createAccount: CreateAccountVm; //Contains your fields & finished bool
socialProfiles: SocialProfilesVm; //Contains your fields & finished bool
personalDetails: PersonalDetailsVm; //Contains your fields & finished bool
//Store index here if you want, although I don't think you need it
}
#Component({})
export class SignUp {
model = new SignUpVm(); //from sign_up_vm.ts (e.g)
}
//Copy this for personalDetails & createAccount
#Component({})
export class SocialProfiles {
#Input() model: SignUpVm;
}