I have a angular2 version debounce input control, template like below.
<input type="text" [ngFormControl]="compInput" placeholder="demo input" />
In my component.ts
import {Component} from "angular2/core";
import {Control} from "angular2/common";
#Component({
...
)
export class Demo{
private compInput = new Control();
constructor(){
this.compInput.valueChanges.subscribe(() => {});
}
}
these code works until I upgrade my angular2 version to latest.
It seems form usage has changed.
I changed [ngFormControl] to ngControl and Control to FormControl from "#angular/forms", but doesn't work.
Does anyone know where I am wrong about the new usage and how to fix?
Here's a simple example using ngModel
import {Component, Input, Output, HostListener, EventEmitter, ChangeDetectionStrategy} from '#angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
#Component({
moduleId: module.id,
selector: 'user-search',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<form role="search">
<div class="form-group">
<input
class="form-control"
name="input"
type="text"
placeholder="Search user"
[(ngModel)]="input"
(keyup)="keyup$.next($event.target.value)"
/>
</div>
</form>
`
})
export class UserSearchComponent {
input: string;
keyup$ = new Subject<string>();
#HostListener('window:keyup', ['$event'])
cancelSearch(event) {
if (event.code === 'Escape') {
this.input = undefined;
this.keyup$.next(undefined);
}
}
#Output() search: Observable<string> = this.keyup$
.debounceTime(700)
.distinctUntilChanged();
}
Thanks for all your help. I have find the answer for my question with help of my colleague. Here it is.
template.html
<form #form="ngForm">
<input name="nameInput" [(ngModel)]="componentName" #nameInput="ngModel">
</form>
component.ts
import {Component, ViewChild} from "#angular/core";
import {NgModel} from "#angular/common";
#Component({...})
export class Demo{
#ViewChild('nameInput') nameInput:NgModel;
componentName:string;
ngAfterViewInit(){
this.nameInput.update //or this.nameInput.control.valueChanges
.subscribe((val:any) => {console.log("value update", val);})
}
}
Related
Angular version: 5.0.0
angular/material version: 5.2.4
I've got this form:
<form #updateForm="ngForm">
<mat-form-field>
<input type="text" matInput [formControl]="studentFormControl [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let student of students" [value]="student">
{{student}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
And I've got this component:
import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '#angular/forms';
import { MatInputModule, MatAutocompleteModule, MatFormFieldModule } from '#angular/material';
export class DashboardComponent implements OnInit {
this.studentFormControl = new FormControl();
this.students = ['hi', 'hello'];
...
}
Although the form shows up, the autocomplete box remains dimensionless without options rendered within:
screenshot of input/autocomplete box
It should be noted as well that the form is nested within an ngbModal. Any ideas what could be happening here?
So I'm no expert here, but from what I understand, the autocomplete function requires an observable of sorts, at least if you want to be able to filter results as you type, to be selected. Since you are using an array you need to first turn it into an observable. As your array is loaded immediately you would need to use RXJS's subjects and more specifically the BehaviorSubject.
Once it becomes an observable you can then call it using the asyncpipe on your form.
This is not to say you couldn't have done it with an array and not used the asyncPipe, however that array would have to be loaded in OnInit.
See the example for both
import { Observable, from, Subscription, BehaviorSubject } from 'rxjs';
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '#angular/forms';
import { MatInputModule, MatAutocompleteModule, MatFormFieldModule } from '#angular/material';
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
studentFormControl = new FormControl();
studentFormControl1 = new FormControl();
array = ['test','one','two'];
array1=[];
arrayObs: Observable<any>;
arrayBehObs = new BehaviorSubject(this.array);
constructor() { }
ngOnInit() {
this.array1.push('test','one','two');
this.arrayObs = this.returnAsObs();
}
private returnAsObs() {
return this.arrayBehObs.asObservable();
}
}
<form #updateForm="ngForm">
<input type="text" matInput [formControl]="studentFormControl" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let student of arrayObs|async" [value]="student">
{{student}}
</mat-option>
</mat-autocomplete>
<input type="text" matInput [formControl]="studentFormControl1" [matAutocomplete]="auto1">
<mat-autocomplete #auto1="matAutocomplete">
<mat-option *ngFor="let student of array1" [value]="student">
{{student}}
</mat-option>
</mat-autocomplete>
</form>
I'm trying to get the value of an input field in my first ever Angular form, but it is always undefined, and I can't figure out why. I'm importing FormsModule correctly, and I can reference the form object fine, so I must be missing something obvious.
My components HTML
<form #searchValue='ngForm' class="" (ngSubmit)='submitSearch(searchValue)'>
<div>
<input type="text" name="q" placeholder="search">
</div>
</form>
And my components ts method (Shortened)
import { Component, OnInit } from '#angular/core';
import { FormsModule } from '#angular/forms';
#Component({
selector: 'google-search',
templateUrl: './google.component.html',
styleUrls: ['./google.component.css']
})
export class GoogleComponent implements OnInit {
constructor() { }
ngOnInit() {
}
submitSearch(formData) {
console.log(this.searching);
console.log(formData.value.q);
}
}
Any ideas to why this is?
You need to mark the input with ngModel so angular will know that this is one of form's controls:
<input type="text" ngModel name="q" placeholder="search">
Or you can define the variable first in your component, and then bind the input to it via [(ngModel)] directive:
export class GoogleComponent implements OnInit {
q: string;
submitSearch() {
console.log(this.q);
}
}
<form class="" (ngSubmit)='submitSearch()'>
<div>
<input type="text" name="q" [(ngModel)]="q" placeholder="search">
</div>
</form>
One way binding (just [ngModel]="q") could be enough if you just want to read the value from input.
Some like this should work..
Maybe you want to read about model binding and forms.
html component
<form #searchValue='ngForm' class="some-css-class" (ngSubmit)='submitSearch()'>
<div>
<input type="text" name="q" [(ngModel)]="searchValue" placeholder="search">
<input type="submit" name="btn" placeholder="Submit">
</div>
</form>
In component.ts
import { Component, OnInit } from '#angular/core';
import { FormsModule } from '#angular/forms';
#Component({
selector: 'google-search',
templateUrl: './google.component.html',
styleUrls: ['./google.component.css']
})
export class GoogleComponent implements OnInit {
searchValue: string = '';
constructor() { }
ngOnInit() { }
submitSearch() {
console.log(this.searchValue);
}
}
While working on Angular 2 form submit I run into a problem. When I create an object inside a component everything works well and my form gets submit via post method. But when I am using an object from a class outside the component my form sends a get request with url http://localhost:4200/blog?title=sss&content=ssssss
Does anyone know why this is happening?
Template:
<form (ngSubmit)="onSubmit()" #f="ngForm">
<!-- <form #f="ngForm" (ngSubmit)="onSubmit(f)">-->
<div class="form-group">
<label for="title">Tytuł</label>
<textarea class="form-control" id="title" rows="1"
ngModel name = "title" required minlength="3" #title="ngModel"></textarea>
<span class="help-block" *ngIf="!title.valid && title.touched">Wprowadzono za krótki tekst (minum to 3 znaki).</span>
<label for="content">Zawartość:</label>
<textarea class="form-control" id="content" rows="3"
ngModel name = "content" required minlength="3" #content="ngModel"></textarea>
<span class="help-block" *ngIf="!content.valid && content.touched">Wprowadzono za krótki tekst (minum to 3 znaki).</span>
</div>
<button type="submit" class="btn btn-primary"
[disabled] ="!f.valid"
>Wyślij</button>
</form>
Component:
import {Component, OnInit, ViewChild} from '#angular/core';
import {NgForm} from "#angular/forms";
import {Blog} from "../../shared/blog";
import {BlogService} from "../../services/blog.service";
#Component({
selector: 'app-blog-form',
templateUrl: './blog-form.component.html',
styleUrls: ['./blog-form.component.css']
})
export class BlogFormComponent implements OnInit {
#ViewChild('f') form: NgForm;
errorMessage: string;
/* this works well
blog = {
title: '',
content: '',
dateCreated: ''
}*/
//this doesn't work
blog: Blog;
ngOnInit(){}
onSubmit(){
this.blog.title = this.form.value.title;
this.blog.content = this.form.value.content;
}
}
The Blog class. I tried both this:
export class Blog {
constructor(public title = '', public content = '', public dateCreated = ''){}}
And this:
export class Blog {
constructor(public title : string, public content : string, public dateCreated : string){}}
Thanks for any help :)
I am not sure why this is happening but try not using this.form.value.
onSubmit(){
this.blog.title = this.form.title;
this.blog.content = this.form.content;
console.log(this.blog);
}
Use of value posts back your page. Now this code should work.
I had a Form Validation working but after updating Ionic doesn't work. Here's my code:
form.html
<ion-header>
<ion-navbar>
<ion-title>
Authorization Form Demo
</ion-title>
</ion-navbar>
</ion-header>
<ion-content class="home" padding>
<form [ngFormModel]="authForm" (ngSubmit)="onSubmit(authForm.value)">
<ion-item [class.error]="!username.valid && username.touched">
<ion-label floating>Username</ion-label>
<ion-input type="text" value="" [ngFormControl]="username"></ion-input>
</ion-item>
<div *ngIf="username.hasError('required') && username.touched"
class="error-box">* Username is required!</div>
<div *ngIf="username.hasError('minlength') && username.touched"
class="error-box">* Minimum username length is 8!</div>
<div *ngIf="username.hasError('checkFirstCharacterValidator') && username.touched"
class="error-box">* Username cant't start with number!</div>
<ion-item [class.error]="!password.valid && password.touched">
<ion-label floating>Password</ion-label>
<ion-input type="text" value="" [ngFormControl]="password" ></ion-input>
</ion-item>
<div *ngIf="password.hasError('required') && password.touched"
class="error-box">* Password is required</div>
<div *ngIf="password.hasError('minlength') && password.touched"
class="error-box">* Minimum password length is 8!</div>
<div *ngIf="password.hasError('checkFirstCharacterValidator') && password.touched"
class="error-box">* Password cant't start with number!</div>
<br/><br/>
<button type="submit" class="custom-button" [disabled]="!authForm.valid" block>Submit</button>
</form>
</ion-content>
form.ts
import {Component} from '#angular/core';
import {NavController} from 'ionic-angular';
import {FORM_DIRECTIVES, FormBuilder, ControlGroup, Validators, AbstractControl} from '#angular/common';
import {CustomValidators} from '../validators/CustomValidators';
#Component({
templateUrl: 'build/pages/form/form.html',
directives: [FORM_DIRECTIVES]
})
export class FormPage {
authForm: ControlGroup;
username: AbstractControl;
password: AbstractControl;
constructor(private navController: NavController, private fb: FormBuilder) {
this.authForm = fb.group({
'username': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])],
'password': ['', Validators.compose([Validators.required, Validators.minLength(8), CustomValidators.checkFirstCharacterValidator])]
});
this.username = this.authForm.controls['username'];
this.password = this.authForm.controls['password'];
}
onSubmit(value: string): void {
if(this.authForm.valid) {
console.log('Submitted value: ', value);
}
}
}
CustomValidators.ts
import { Control, ControlGroup } from "#angular/common";
interface ValidationResult {
[key: string]: boolean;
}
export class CustomValidators {
public static checkFirstCharacterValidator(control: Control): ValidationResult {
var valid = /^\d/.test(control.value);
if (valid) {
return {checkFirstCharacterValidator: true};
}
return null;
}
}
Somebody know what changes I need to do for working fine?
Thanks in advance.
Best regards.
Beta11 of Ionic2 has made breaking changes in form handling, you can read more here.
form.ts edit two lines to look like this:
import {FORM_DIRECTIVES, FormBuilder, FormGroup, Validators, AbstractControl} from '#angular/forms';
authForm: FormGroup;
You need to import new forms component from #angular/forms not the deprecated one #angular/common and change deprecated ControlGroup to FormGroup
In form.html edit one line to:
<form [formGroup]="authForm" (ngSubmit)="onSubmit(authForm.value)" novalidate>
Change deprecated ngFormModel to formGroup and consider adding novalidate attribute to your form.
To make your custom validator work you also have to change two lines in CustomValidators.ts but I didnt have time to read all changes and never used custom validators before. So this may require more work
import { FormControl, FormGroup } from "#angular/forms";
public static checkFirstCharacterValidator(control: FormControl): ValidationResult {
I have a simple select with an ngFor and the select box is empty until I type into one of the other fields and then it magically shows the data even though I know it completed the data call previously.
My view
<div class="form-group col-md-3">
<label for="payerId">PayerId</label>
<select class="form-control">
<option *ngFor="#item of model.payers">{{item.HealthPlanName}}</option>
</select>
</div>
<div class="form-group col-md-3">
<label for="providerType">Provider Type</label>
<input type="text" class="form-control" [(ngModel)]="model.providerType"/>
</div>
My Component
import {Component, Injectable, OnInit, View} from "angular2/core";
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgForm, NgFormControl, NgFor} from "angular2/common";
import {CoverageService} from "../../services/coverage/coverage.services";
import "rxjs/Rx";
#Component({
selector: "coverage",
providers: [CoverageService]
})
#View({
templateUrl: "/Scripts/appScripts/components/coverage/coverage.html",
directives: [CORE_DIRECTIVES, FORM_DIRECTIVES, NgForm, NgFormControl, NgFor, PayerSelector]
})
export class CoverageComponent implements OnInit {
model = new CoverageRequest();
constructor(private coverageService: CoverageService) {}
ngOnInit() {
this.getPayers();
}
getPayers() {
this.coverageService.getPayers()
.subscribe(resp => {
this.model.payers = resp;
});
}
}
Really scratching my head.
Here are the libraries I am using:
"dependencies": {
"angular2": "2.0.0-beta.0",
"systemjs": "^0.19.20",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.10"
}
My Service
import {Http, Response} from "angular2/http";
import {Injectable} from "angular2/core";
import {COVERAGE_BASE} from "../../config";
import "rxjs/Rx";
#Injectable()
export class CoverageService {
constructor(public http: Http) {
}
getPayers(): any {
return this.http.get(COVERAGE_BASE + "/Payers")
.map((response: Response) => response.json());
}
}
Data
[{
"Id": 3817,
"ProviderId": 2,
"ApiPayerId": "00028",
"HealthPlanName": "Georgia Medicaid",
"Type": null,
"PayerSynonyms": null
}, {
"Id": 3818,
"ProviderId": 2,
"ApiPayerId": "00143",
"HealthPlanName": "J. F. Molloy and Associates Inc.",
"Type": null,
"PayerSynonyms": null
}]
Try initiating the model in ngOnInit instead of directly in the class. You will need to use the elvis operator in the view, because the model initially will be undefined. Read more about the elvis operator here: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#sts=The%20Elvis%20operator%20(%20%3F.%20)%20and%20null%20property%20paths
I am not entirely sure but i think it should work.