While following the tutorial for forms at https://angular.io/docs/ts/latest/guide/forms.html
I keep getting undefined errors whenever referring to any of the properties that are defined in the .ts file as long as I use templateUrl and a seperate .html
When I take the same html and place in the .ts file inside `` in template everything works fine.
So my question is: Does the templateURl file need to define scope somehow? The tutorial doesn't seem to cover anything about it and I assumed that it would get access to the component variables that called it.
import { Component } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Guitar } from './guitar';
#Component({
selector: 'guitar-form',
// template: `
// <div class="container">
// <h1>Guitar Form</h1>
// <form>
// <div class="form-group">
// <label for="brand">Brand</label>
// <select class="form-control" required
// [(ngModel)]="testmodel.brand" name="brand">
// <option *ngFor="let b of brands" [value]="b">{{b}}</option>
// </select>
// TODO: remove this: {{testmodel.brand}}
// </div>
// <div class="form-group">
// <label for="model">Model</label>
// <input type="text" class="form-control" required
// [(ngModel)]="testmodel.model" name="model">
// TODO: remove this: {{testmodel.model}}
// </div>
// <div class="form-group">
// <label for="color">Color</label>
// <input type="text" class="form-control"
// [(ngModel)]="testmodel.color" name="color">
// TODO: remove this: {{testmodel.color}}
// </div>
// <button type="submit" class="btn btn-default">Submit</button>
// </form>
// </div>
// `
templateUrl: 'app/guitar-form.component.html'
})
export class GuitarFormComponent {
brands = ['Fender', 'Gibson', 'Guild', 'Jackson', 'Epiphone', 'Charvel'];
testmodel = new Guitar(69, this.brands[0], 'Stratocaster', 'Black');
submitted = false;
onSubmit() { this.submitted = true; }
// TODO: remove this when we're done
get diagnostic() { return JSON.stringify(this.model); }
}
Funny, the undefined disappeared when I commented it out so I could demonstrate but ironically the diagnostic is no longer working when placed in the html and this was the one aspect that was working earlier. I have verified connectivity on an individual basis...
<div class="container">
<h1>Guitar Form</h1>
<form>
{{ diagnostic }}
<div class="form-group">
<label for="brand">Brand</label>
<select class="form-control" required
[(ngModel)]="testmodel.brand" name="brand">
<option *ngFor="let b of brands" [value]="b">{{b}}</option>
</select>
{{ testmodel.brand }}
</div>
<div class="form-group">
<label for="model">Model</label>
<input type="text" class="form-control" required
[(ngModel)]="testmodel.model" name="model">
TODO: remove this: {{testmodel.model}} -->
</div>
<div class="form-group">
<label for="color">Color</label>
<input type="text" class="form-control"
[(ngModel)]="testmodel.color" name="color">
{{ testmodel.color }}
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
I think you need to add
moduleId: module.id,
to the #Component({...}) decorator.
See also Angular2 - What is the meanings of module.id in component?
Related
I currently have a disabled input box. I use the box to display the sum of two range sliders, where I update the value of the box via JavaScript.
I currently require that the value of the box equals 100 before allowing the form to be submitted. Is there a work-around where I can still disable the box, where it will still adopt the same Bootstrap style formatting (change color from red to green, etc) as a non-disabled box with the 'require' option?
Following a suggestion here, I've updated the code snippet below to almost be what I want. The only thing that I'd like to change, is to make 'rSum', the box that displays the sum, disabled (while still keeping all the validation formatting features). Ideally, I want this sum to adopt the validation feedback rather than the sliders, or other mutable input objects.
function checkSum() {
let currSum = parseInt(document.getElementById('rSum').value);
if (currSum != 100) {
document.getElementById('rSum').setCustomValidity('Must sum to 100%');
return false
} else {
document.getElementById('rSum').setCustomValidity('');
return true
}
}
function updateBoxes() {
const s1 = document.getElementById('range1');
const s2 = document.getElementById('range2');
let currSum = parseInt(s1.value) + parseInt(s2.value);
document.getElementById('rangeValue1').value = (s1.value)+"%";
document.getElementById('rangeValue2').value = (s2.value)+"%";
document.getElementById('rSum').value = (currSum)+"%";
}
// This last function is the original bootstrap validation example, modified to call 'checkSum()' instead
(function () {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.querySelectorAll('.custom-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!checkSum()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="custom-validation" novalidate>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue1" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range1" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group col-md-1">
<input class="form-control" type="text" id="rangeValue2" disabled>
</div>
<div class="form-group col-md-4 col-form-label">
<input type="range" class="form-range" min="0" max="100" step="5" id="range2" value="0" onchange="updateBoxes()" >
</div>
</div>
<div class="mb-3 row">
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Probabilities must add up to 100%
</div>
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-6 offset-md-1">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
A couple of ways to do this. Here I use an example form with some inputs that can be used in the slider validation (one is a range slider but could be a simple number input also).
I set an event handler for those elements, associate them using data attributes and then; very verbosely and a bit ugly for clarity, use them in a function.
function checkSum(event) {
const fearRequird = this.fearNeed;
const myFear = event.target;
const associated = document.querySelector(myFear.dataset.related);
const result = this.sumEl;
const thisValue = parseInt(myFear.value);
const associatedValue = parseInt(associated.value);
let currSum = thisValue + associatedValue;
result.value = currSum;
let isValidSlider = currSum >= fearRequird;
result.classList.toggle("is-valid", isValidSlider);
result.classList.toggle("is-invalid", !isValidSlider);
let t = isValidSlider ? '' : `You Fear ${thisValue} and ${associatedValue} total ${currSum}. You need total ${fearRequird} fear`;
result.setCustomValidity(t);
result.closest('.form-group').querySelector('.invalid-feedback').textContent = t;
return isValidSlider;
}
(function() {
'use strict'
// Fetch all the forms we want to apply custom Bootstrap validation styles to
let forms = document.querySelectorAll('.needs-validation');
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false)
});
const fearNeed = 100;
const myFears = document.querySelectorAll('.fear-factor');
const needs = {
fearNeed: fearNeed,
sumEl: document.querySelector('#rSum')
};
myFears.forEach((fearElement) => {
fearElement.addEventListener('change', checkSum.bind(needs), false);
});
})();
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<form class="row g-3 needs-validation mx-1 my-2" novalidate>
<div class="form-group">
<input type="text" class="form-control text-center" id="rSum" placeholder="100%" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Fears must add up to 100%
</div>
</div>
<div class="col-md-4">
<label for="validationCustomUsername" class="form-label">Fish Name</label>
<div class="input-group has-validation">
<span class="input-group-text" id="inputGroupPrepend">Fish</span>
<input type="text" class="form-control" id="validationCustomFishname" aria-describedby="inputGroupPrepend" required>
<div class="invalid-feedback">
Must catch a fish.
</div>
<div class="valid-feedback">
Looks like an good catch!
</div>
</div>
</div>
<div class="col-md-3">
<label for="validationCustomFearMet" class="form-label">Scary cats fear</label>
<div class="input-group has-validation">
<input type="number" class="form-control fear-factor" min="0" max="100" step="1" value="13" id="validationCustomFearMet" data-related="#customRange3" required />
<span class="input-group-text" id="inputGroupPrepend">%</span>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
<div class="invalid-feedback">
Please provide scary cats fear as a percent 0-100.
</div>
</div>
</div>
<div class="mx-1">
<label for="customRange3" class="form-label">Fear range</label>
<input type="range" class="form-range fear-factor" min="0" max="100" step="1" value="0" data-related="#validationCustomFearMet" id="customRange3">
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</form>
I'm trying to create a submit form, but all my v-model are giving me this error.
Here is one example of how I'm creating the form inputs:
<template>
<div class="card mx-xl-5">
<!-- Card body -->
<div class="card-body">
<div>
<form v-on:submit.prevent="pushLocation">
<div class="form-row">
<div class="col-md-6">
<label>Name:</label>
<input
type="text"
class="form-control"
v-model="txtLocationName"
/>
</div>
<div class="col-md-6"> <div class="card mx-xl-5">
<label>Description</label>
<input
type="text"
class="form-control"
v-model="txtLocDescription"
placeholder="Description"
/>
</div>
</div>
<div class="form-group">
<label for="type">Tipo de localização</label>
<select class="form-control" id="type" v-model="typeLoc">
<option value="museum">Museum</option>
<option value="restaurant">Restaurant</option>
<option value="tourist_attraction">Monument</option>
<option value="art_gallery">Galery</option>
</select>
</div>
<div class="col-md-6">
<label>Imagem</label>
<input type="url" class="form-control" v-model="urlImg" placeholder="Link" />
</div>
<div class="form-group row">
<div class="col-auto">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</div>
</form>
</div>
</div>
And here is how I'm setting the properties on my script:
name: "LocationList",
data: function() {
return {
id: 0,
txtLocationName: "",
txtLocDescription: "",
typeLoc: "",
urlImg: "",
listLocation: [],
locationChecked: false
};},
methods: {
getLastLocationId() {
if (this.listLocation.length) {
return this.listLocation[this.listLocation.length - 1].id;
} else {
return 0;
}
},
checkLocationName() {
if (this.listLocation.length) {
for (const location of this.listLocation) {
if (location.Name == this.txtLocName) {
(this.locationChecked = false),
alert("nome de localização indisponivel");
} else {
this.userChecked = true;
}
}
}
},
pushLocation() {
this.checkLocationName();
this.getCoordenates();
if (this.locationChecked == true) {
this.$store.commit("ADD_USER", {
id: this.getLastLocationId() + 1,
Name: this.txtLocationName,
Description: this.txtLocDescription,
Type: this.typeLoc,
imgLink: this.urlImg
});
this.$router.push({ name: "adminLocations" });
} else {
alert("erro no registo");
}
}
}
I've done this type of forms multiple times, yet I can figure out why i'm having this error.I added the rest of my vue component. I get the error on all the property and methods, not only on "urlImg".Meaning all the properties that exist in the data and are in the form are giving me this error.
One last point, the final function, pushLocation() is also giving the error, saying that it is not a real function.
I am building an app using Angular 4.0.2. How can I add a button to a form to add a new row of input and a delete button for a particular row to delete? I mean that I want a form something like this. I want my form to look something like this:
.
Here is my code:
add-invoice.component.html
<h3 class="page-header">Add Invoice</h3>
<form [formGroup]="invoiceForm">
<div formArrayName="itemRows">
<div *ngFor="let itemrow of itemRows.controls; let i=index" [formGroupName]="i">
<h4>Invoice Row #{{ i + 1 }}</h4>
<div class="form-group">
<label>Item Name</label>
<input formControlName="itemname" class="form-control">
</div>
<div class="form-group">
<label>Quantity</label>
<input formControlName="itemqty" class="form-control">
</div>
<div class="form-group">
<label>Unit Cost</label>
<input formControlName="itemrate" class="form-control">
</div>
<div class="form-group">
<label>Tax</label>
<input formControlName="itemtax" class="form-control">
</div>
<div class="form-group">
<label>Amount</label>
<input formControlName="amount" class="form-control">
</div>
<button *ngIf="i > 1" (click)="deleteRow(i)" class="btn btn-danger">Delete Button</button>
</div>
</div>
<button type="button" (click)="addNewRow()" class="btn btn-primary">Add new Row</button>
</form>
<p>{{invoiceForm.value | json}}</p>
Here is my code for add-invoice.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormControl, FormArray, FormGroup } from '#angular/forms';
#Component({
selector: 'app-add-invoice',
templateUrl: './add-invoice.component.html',
styleUrls: ['./add-invoice.component.css']
})
export class AddInvoiceComponent implements OnInit {
invoiceForm: FormGroup;
constructor(
private _fb: FormBuilder
) {
this.createForm();
}
createForm(){
this.invoiceForm = this._fb.group({
itemRows: this._fb.array([])
});
this.invoiceForm.setControl('itemRows', this._fb.array([]));
}
get itemRows(): FormArray {
return this.invoiceForm.get('itemRows') as FormArray;
}
addNewRow(){
this.itemRows.push(this._fb.group(itemrow));
}
ngOnInit(){
}
}
Here's a shortened version of your code:
When you init your form, you can add one empty formgroup inside your formArray:
ngOnInit() {
this.invoiceForm = this._fb.group({
itemRows: this._fb.array([this.initItemRows()])
});
}
get formArr() {
return this.invoiceForm.get('itemRows') as FormArray;
}
Then the function:
initItemRows() {
return this._fb.group({
// list all your form controls here, which belongs to your form array
itemname: ['']
});
}
Here is the addNewRow and deleteRow functions:
addNewRow() {
this.formArr.push(this.initItemRows());
}
deleteRow(index: number) {
this.formArr.removeAt(index);
}
Your form should look like this:
<form [formGroup]="invoiceForm">
<div formArrayName="itemRows">
<div *ngFor="let itemrow of formArr.controls; let i=index" [formGroupName]="i">
<h4>Invoice Row #{{ i + 1 }}</h4>
<div>
<label>Item Name</label>
<input formControlName="itemname">
</div>
<button type="button" (click)="deleteRow(i)" *ngIf="formArr.controls.length > 1" >
Delete
</button>
</div>
</div>
<button type="button" (click)="addNewRow()">Add new Row</button>
</form>
Here's a
DEMO
My error is
EXCEPTION: Error: Uncaught (in promise): Template parse errors:
Can't bind to 'ngFormModel' since it isn't a known native property ("
<h3 class = "head">MY PROFILE</h3>
<form [ERROR ->][ngFormModel]="form" (ngSubmit)="onSubmit(form.value)">
<div class="row">
"): a#3:7
There is no directive with "exportAs" set to "ngForm" ("stname</label>
<input type="text" id="facebook" class="form-control" ngControl="firstname" [ERROR ->]#firstname="ngForm" >
</div>
"): a#9:85
There is no directive with "exportAs" set to "ngForm" ("/label>
<input type="text" id="facebook" class="form-control col-xs-3" ngControl="lastname" [ERROR ->]#lastname="ngForm" >
</div>
My template,
<h3 class="head">MY PROFILE</h3>
<form [ngFormModel]="form" (ngSubmit)="onSubmit(form.value)">
<div class="row">
<div class="form-group">
<label class="formHeading">firstname</label>
<input type="text" id="facebook" class="form-control" ngControl="firstname" #firstname="ngForm">
</div>
<div *ngIf="firstname.touched">
<div *ngIf="!firstname.valid" class="alert alert-danger">
<strong>First name is required</strong>
</div>
</div>
<div class="form-group">
<label class="formHeading">lastname</label>
<input type="text" id="facebook" class="form-control col-xs-3" ngControl="lastname" #lastname="ngForm">
</div>
<div *ngIf="lastname.touched">
<div *ngIf="!lastname.valid" class="alert alert-danger">
<strong>Last name is required</strong>
</div>
</div>
<div class="form-group">
<label class="formHeading">Profilename</label>
<input type="text" id="facebook" class="form-control col-xs-3" ngControl="profilename" #profilename="ngForm">
</div>
<div class="form-group">
<label class="formHeading">Phone</label>
<input type="text" id="facebook" class="form-control col-xs-3" ngControl="phone" #phone="ngForm">
</div>
<div *ngIf="phone.touched">
<div *ngIf="!phone.valid" class="alert alert-danger">
<strong>Phone number is required</strong>
</div>
</div>
<label class="formHeading">Image</label>
<input type="file" name="fileupload" ngControl="phone">
<div class="form-row btn">
<button type="submit" class="btn btn-primary " [disabled]="!form.valid">Save</button>
</div>
</div>
</form>
My Component
import {Component} from '#angular/core';
import { Http, Response, Headers} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {contentHeaders} from '../headers/headers';
import {FORM_DIRECTIVES} from '#angular/forms';
import {Router, ROUTER_DIRECTIVES} from '#angular/router';
import {Control, FormBuilder, ControlGroup, Validators} from '#angular/common';
#Component({
templateUrl: './components/profile/profile.html',
directives: [ROUTER_DIRECTIVES, FORM_DIRECTIVES],
})
export class Profile {
http: Http;
form: ControlGroup;
constructor(fbld: FormBuilder, http: Http, public router: Router) {
this.http = http;
this.form = fbld.group({
firstname: ['', Validators.required],
lastname: ['', Validators.required],
profilename: ['', Validators.required],
image: [''],
phone: [''],
});
}
onSubmit(form: any) {
console.log(form);
let body = JSON.stringify(form);
var headers = new Headers();
this.http.post('http://localhost/angular/index.php/profile/addprofile', body, {
headers: headers
})
.subscribe(
response => {
if (response.json().error_code == 0) {
alert('added successfully');
this.router.navigate(['/demo/professional']);
} else {
alert('fail');
}
});
}
}
The problem is that you're still importing from common and especially using the instructions of the old forms.
Import correctly the components for new forms:
import {FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES} from '#angular/forms';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
And correct the component:
#Component({
...
directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES]
})
export class AppComponent {
form: FormGroup;
constructor(fbld: FormBuilder) {
this.form = fbld.group({
...
});
}
...
}
Then correct the view: ngFormModel has been replaced by formGroup, and use formControl for your fields:
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
<div class="row">
<div class="form-group">
<label class="formHeading">firstname</label>
<input type="text" id="facebook" class="form-control" [formControl]="form.controls['firstname']" >
</div>
<div *ngIf ="form.controls['firstname'].touched">
<div *ngIf ="!form.controls['firstname'].valid" class = "alert alert-danger">
<strong>First name is required</strong>
</div>
</div>
...
<div class="form-row btn">
<button type="submit" class="btn btn-primary" [disabled]="!form.valid">Save</button>
</div>
</div>
</form>
Edit. From Angular 2.0.0-rc.5, is necessary to remove the directives from the component and import the form modules in AppModule:
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
#NgModule({
imports: [
...
FormsModule,
ReactiveFormsModule
],
...
bootstrap: [AppComponent]
})
export class AppModule { }
If you use a shared module, do not forget to export them:
#NgModule({
imports: [
...
FormsModule,
ReactiveFormsModule
],
exports: [
...
FormsModule,
ReactiveFormsModule
]
})
export class SharedModule { }
I had the same issue. What I did to solve it:
remove the tag, and add (click)-function to the button
checked my backend: there was an error in some special event... fixed it
Now it doesn't fire twice anymore.
So double check this! You never know...
Just import the following statement in ts,
import {FORM_DIRECTIVES, FormBuilder, Validators, REACTIVE_FORM_DIRECTIVES} from '#angular/forms';
directives: [CORE_DIRECTIVES, ROUTER_DIRECTIVES, FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES],
Make the following changes in templates,
<h3 class = "head">MY PROFILE</h3>
<form [ngFormModel]="form" (ngSubmit)="onSubmit(form.value)">
<div class="row">
<div class="form-group">
<label class="formHeading">firstname</label>
<input type="text" id="facebook" class="form-control" [formControl]="form.controls['firstname']">
</div>
<div *ngIf ="firstname.touched">
<div *ngIf ="!firstname.valid" class = "alert alert-danger">
<strong>First name is required</strong>
</div>
</div>
<div class="form-group">
<label class="formHeading">lastname</label>
<input type="text" id="facebook" class="form-control col-xs-3" [formControl]="form.controls['lastname']">
</div>
<div *ngIf ="lastname.touched" >
<div *ngIf = "!lastname.valid" class = "alert alert-danger">
<strong>Last name is required</strong>
</div>
</div>
<div class="form-group">
<label class="formHeading">Profilename</label>
<input type="text" id="facebook" class="form-control col-xs-3" [formControl]="form.controls['profilename']" >
</div>
<div class="form-group">
<label class="formHeading">Phone</label>
<input type="text" id="facebook" class="form-control col-xs-3" [formControl]="form.controls['phone']">
</div>
<div *ngIf ="phone.touched" >
<div *ngIf = "!phone.valid" class = "alert alert-danger">
<strong>Phone number is required</strong>
</div>
</div>
<div class="form-row btn">
<button type="submit" class="btn btn-primary " [disabled]="!form.valid">Save</button>
</div>
Finally do this in your bootstrapping,
import {provideForms, disableDeprecatedForms} from '#angular/forms';
bootstrap(MyDemoApp, [
provideForms(),
disableDeprecatedForms()]);
Using Angular to design a form with 3 inputs (based on Scotch.IO tutorial for Node+Express+Angular).
I would like the user to compulsorily select values for each input before submitting the form. If he doesn't, then I would like to display an error message.
<form>
<div class="form-group">
Start Date: <input type="date" class="form-control input-lg text-center" ng-model="formData.fromDate" placeholder="yyyy-MM-dd">
</div>
<div class="form-group">
End Date: <input type="date" class="form-control input-lg text-center" ng-model="formData.toDate" placeholder="yyyy-MM-dd">
</div>
<div class="form-group">
Report Type: <select class="form-control input-lg text-center" ng-model="formData.reportType">
<option value="csv">CSV</option>
<option value="pdf">PDF</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-lg" ng-click="findStat()">Add</button>
</form>
In other words, i would not like to pass 'undefined' values back to my Node.js code.
I have tried using 'required' options, which doesn't prevent undefined values from being passed back.
Give your form a name:
<form name="myForm">
Also give your inputs a name, and add validity constraints on them (required, etc.):
<input type="date" name="date" ...
Then in your findStat() function, you can access the form and check if it's valid:
$scope.findStat = function() {
if ($scope.myForm.$invalid) {
$scope.displayError = true;
}
else {
$scope.displayError = false;
...
}
}
See http://code.angularjs.org/1.2.15/docs/api/ng/directive/form and http://code.angularjs.org/1.2.15/docs/api/ng/type/form.FormController for more information.