I have set of dates and I want to enable only those dates in <mat-datepicker>.
"ListOfDates": [
{
"startDate": "2018-01-01T08:00:00"
},
{
"startDate": "2018-01-02T08:00:00"
},
{
"startDate": "2018-01-03T09:00:00",
}]
This is my html code:
<mat-form-field>
<input matInput
[matDatepicker]="picker"
[matDatepickerFilter]="dateFilter"
placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
In my Component.ts file:
#Component({...})
export class SomeComponent.ts {
dateFilter = (date: Date) => date.getDate()
}
Can anyone help on this?
You are going to need a custom validator. More details can be found here: https://material.angular.io/components/datepicker/overview#date-validation
Essentially you give a function that takes in a date and returns a boolean indicating whether that date is valid. In your case you want to in your controller check if the given date is a member of your list. Here is a basic implementation:
HTML:
<mat-form-field class="example-full-width">
<input matInput [matDatepickerFilter]="myFilter" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
TS:
import {Component} from '#angular/core';
/** #title Datepicker with filter validation */
#Component({
selector: 'datepicker-filter-example',
templateUrl: 'datepicker-filter-example.html',
styleUrls: ['datepicker-filter-example.css'],
})
export class DatepickerFilterExample {
validDates = {
"2018-01-01T08:00:00": true,
"2018-01-02T08:00:00": true
}
myFilter = (d: Date): boolean => {
// Using a JS Object as a lookup table of valid dates
// Undefined will be falsy.
return validDates[d.toISOString()];
}
}
myFilter = (d: Date): boolean => {
let enableFlag = false;
this.ListOfDates.some((date) => {
if (date.startDate === d) { // You can use any other comparison operator used by date object
enableFlag = true;
return true;
}
})
return enableFlag;
}
Note: You will have to format the d and dates in ListOfDates to a standard format of your choice
Related
I have a problem with React, so I created script and it doesn't work.
This should:
Render first state step (it's working) (Component First)
Here is error, it don't see default values.(name & email
After click Save And Continue it should save files to data.
And going to next steps in cases.
The error is
bundle.js:34147 Uncaught ReferenceError: email is not defined
function send(e){
e.preventDefault()
}
function nextStep(){
this.setState({
step:this.state.step + 1
})
}
function nextStep(){
this.setState({
step:this.state.step - 1
})
}
function saveAndContinue(e) {
e.preventDefault()
// Get values via this.refs
var data = {
name : this.refs.name.getDOMNode().value,
email : this.refs.email.getDOMNode().value,
}
this.props.saveValues(data)
this.props.nextStep()
};
var fieldValues = [
name : null,
email : null,
];
function saveValues(fields) {
return (
fieldValues = Object.assign({}, fieldValues, fields)
);
}
class Registration extends React.Component{
constructor () {
super()
this.state = {
step:1
}
}
render() {
switch (this.state.step) {
case 1:
return <First fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues} />
case 2:
return <Two fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues}/>
case 3:
return <Third fieldValues={fieldValues}
nextStep={this.nextStep}
previousStep={this.previousStep}
saveValues={this.saveValues}/>
case 4:
return <Success fieldValues={fieldValues} />
}
}
}
class First extends React.Component{
render(){
return(
<form onSubmit ={send}>
<div className="group">
<input className="text" type="text" ref="name" defaultValue={this.props.fieldValues.name}/>
<span className="highlight"></span>
<span className="bar"></span>
<label>Write Name</label>
</div>
<div className="group">
<input className="text" type="email" ref="email" defaultValue={this.props.fieldValues.email} />
<span className="highlight"></span>
<span className="bar"></span>
<label>Write Your Mail</label>
</div>
<button onClick={this.saveAndContinue}>Save and Continue</button>
</form>
)
}
}
There is no Two, Third and Success classes in your code, so I'm assuming they are similar to the First class.
A global function doesn't need this keyword. But in this case, you have to put saveAndContinue inside First class if it need to access the state.
In React, normally you don't have to set default value for input.
Link the input value to the state, and then setState in onChange event.
The string in placeholder is shown when the state is empty.
The code below shows how to work with input tag in React:
<input
value={this.state.inputValue}
onChange={e => {
this.setState({ inputValue: e.target.value });
}}
type="text"
placeholder="default value"
/>
Note that the state will updates onChange rather than click the save button.
Does this solve your problem?
I'm using FormBuilder for make JSON data,
I have made this form using FormBuilder, FormGroup, Validators, FormControl
this is my forms code
<form [formGroup]="SearchForm" (ngSubmit)="search(SearchForm.value)" name="SearchForms">
<input type="text" formControlName="checkin" value="12:00" placeholder="12:00" readonly> In
<input type="text" formControlName="checkout" value="10:00" placeholder="10:00" readonly> Out
<input type="text" formControlName="guest"> Guest
<input type="text" formControlName="room"> Room
<select formControlName="position">
<option value="sky">sky</option>
<option value="earth">Earth</option>
</select>
<input type="hidden" formControlName="date" name="date" value="{{selected_date}}">
<input type="hidden" formControlName="location" name="location" value="{{location}}">
<button class="btn shadow" type="submit"> Search </button>
</form>
and this my component.ts file
export class HomeComponent implements OnInit {
http: any;
SearchForm : FormGroup;
post:any;
location: string ='';
date:string = '';
checkin:string='';
checkout:string='';
guest:number;
room:number;
position:string='';
constructor(private fb: FormBuilder)
{
this.SearchForm = fb.group({
'location' : [null],
'date' : [null],
'checkin' : [null],
'checkout' : [null],
'guest' : [null],
'room' : [null],
'position' : [null],
});
}
search(post)
{
this.location = post.location;
this.date = post.date;
this.checkin = post.checkin;
this.checkout = post.checkout;
this.guest = post.guest;
this.room = post.room;
this.position = post.position;
this.http.post('http://localhost:4200/searchrequest',JSON.stringify(this.SearchForm))
}
ngOnInit()
{
this.SearchForm = new FormGroup(
{
location: new FormControl(),
date: new FormControl(),
checkin: new FormControl(),
checkout: new FormControl(),
guest: new FormControl(),
room: new FormControl(),
position:new FormControl()
});}
I have no idea what I should fo next for post data from SearchForm I have made.
Any help form my project? if someone has a link for example you can share it here.
Thanks before
search(post)
{
this.location = post.location;
this.date = post.date;
this.checkin = post.checkin;
this.checkout = post.checkout;
this.guest = post.guest;
this.room = post.room;
this.position = post.position;
this.http.post('http://localhost:4200/searchrequest',JSON.stringify(this.SearchForm))
}
should be
search(post)
{
this.http.post('http://localhost:4200/searchrequest',JSON.stringify(post))
}
you are currently assigning all the form values to the component Instance members when you can just as easily send the entire form value.
and you also initialize the searchForm twice, once with the FormBuilder service and the other time with a new FormGroup instance, which are doing exactly the same thing. you can remove the entire ngOnInit() function since you do it already in the constructor.
angular 5 FormBuilder doc's: https://angular.io/api/forms/FormBuilder
adding #marcidius comment as its a valuable part of the solution.
To fix that error you need to add a private http member to your
constructor: constructor(private fb: FormBuilder, private http: Http)
Also, in your example you don't even need to be passing the SearchForm
to that function since it is a class member already. Reactive Forms`
values are updated via their bindings so any update to the form
elements updates the model automatically. Just call this.searchForm in
the JSON.stringify(...) but don't worry about passing it into the
function.
I needed to get my this.contactForm.value in order to get the object of values . Than i did the stringify
I'm trying to adapt a working form I found for polymer 1.0 in order to work on polymer 2.0 but these two way data bindings don't seem to work.
My template:
<paper-input>
<label>Username</label>
<iron-input bind-value={{formData.username}}><input id="username" type="text" value="{{formData::input}}"></iron-input>
</paper-input>
<paper-input>
<label>Password</label>
<iron-input bind-value={{formData.password}}><input id="password" type="password" value="{{formData::input}}"></iron-input>
</paper-input>
<div class="wrapper-btns">
<paper-button raised class="primary" on-tap="postLogin">Log In</paper-button>
<paper-button class="link" on-tap="postRegister">Sign Up</paper-button>
</div>
My actions:
class MyLogin extends Polymer.Element {
static get is() { return 'my-login'; }
static get properties() {
return {
storedUser: Object,
error: String,
formData: {
type: Object,
value: {},
},
}
}
_setReqBody() {
console.log(this.formData) // <--- THIS LINE!
this.$.registerLoginAjax.body = this.formData;
}
postLogin() {
this.$.registerLoginAjax.url = 'http://localhost:3001/sessions/create';
this._setReqBody();
this.$.registerLoginAjax.generateRequest();
}
}
The indicate line will always print undefined though. What am I doing wrong?
Here's the full code: https://github.com/lpfjustino/PolymerQuickstart/blob/master/web/src/my-login.html
And here's the code mine is based on:
https://auth0.com/blog/build-your-first-app-with-polymer-and-web-components/
paper-input doesn't need any label nor iron-input inside it by default. That only goes for paper-input-container. So the following would be okay
<paper-input label="Username" value="{{formData.username}}"></paper-input>
However if you insist on using paper-input-container instead, then
<paper-input-container>
<label slot="label">Username</label>
<iron-input bind-value="{{formData.username}}" slot="input">
<!-- You don't need to add two-way binding for your input element here
since `iron-input` already handles that for you using its `bind-value`
attribute. -->
<input />
</iron-input>
</paper-input-container>
Also, when you declare an Object property, you should initialize it using a function to insure that each element instance would have its own copy of the property.
static get properties() {
return {
...
formData: {
type: Object,
value: function() {
return {}; // or return { username: '', password: '' }
},
},
};
}
I have a child component which deals with the array of input controls. I want to have a formcontrol over the child component.
I am passing the array of json object, what would be the correct way to bind parent form to the child component's FormArray having 2 form control with Validator required on first.
This is the initial code
<h1>Child</h1>
<div formArrayName="names">
<div *ngFor="let c of names.control">
<input formControlName="firstName">
<input formControlName="lastName">
</div>
</div>
Intention is to bind parent form with the array of input control in the child component. Also form will become invalid if one of the input control in child component doesn't have required field.
http://plnkr.co/edit/HznCJfSEiSV28ERqNiWr?p=preview
I love solve old post :)
The key is that your custom Form Component has inside a FormArray, then use "writeValue" to create the formArray, see stackblitz
#Component({
selector: "my-child",
template: `
<h1>Child</h1>
<div *ngFor="let group of formArray.controls" [formGroup]="group">
<input formControlName="firstName" (blur)="_onTouched()" />
<input formControlName="lastName" (blur)="_onTouched()"/>
</div>
`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: Child,
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: Child,
multi: true
}
]
})
export class Child implements ControlValueAccessor {
formArray: FormArray;
_onChange;
_onTouched;
writeValue(value: any) {
this.formArray = new FormArray(
value.map(x => {
return new FormGroup({
firstName: new FormControl(x.firstName, Validators.required),
lastName: new FormControl(x.firstName, Validators.required)
});
})
);
this.formArray.valueChanges.subscribe(res => {
this._onChange(res);
});
}
registerOnChange(fn: (value: any) => void) {
this._onChange = fn;
}
registerOnTouched(fn: (value: any) => void) {
this._onTouched = fn;
}
validate({ value }: FormControl) {
return !this.formArray || this.formArray.valid ?
null : { error: "Some fields are not fullfilled" };
}
}
You have to use formArrayName directive and *ngFor like this:
<form [formGroup]="form" (ngSubmit)="sayHello()">
<input formControlName="name"><br>
<input formControlName="email"><br>
<div formArrayName="username">
<div *ngFor="let user of username.controls; let i=index">
<my-child formControlName="i"></my-child>
</div>
</div>
<button type="submit">Register</button>
</form>
And with FormBuilder you have to use FormArray as well.
form = new FormGroup({
name: new FormControl('My Name'),
username: new FormArray([
new FormControl("value"),// ControlValueAccesor is applied only to one control, not two. So you cannot use javascript object like you are using below this line.
{firstName:"Anna", lastName:"Smith"},
{firstName:"Peter", lastName:"Jones"}
])
});
For more details, see this doc.
Case 2: passing FormGroup:
form = new FormGroup({
name: new FormControl('My Name'),
username: new FormArray([
new FormGroup({
firstName: new FormControl('Anna'),
lastName: new FormControl('Smith')
}),
new FormGroup({
firstName: new FormControl('Peper'),
lastName: new FormControl('Jones')
}),
])
})
If you are tring to pass the FormGroup as a ngModel parameters, you can't!
I am using 2.0.0-rc.6 in my angular 2 application.
on form submit I am getting this error - self.context.onSubmit is not a function
also it is appending form values in browser.
http://localhost:3000/register
on submit the page reloading and url become like this.
http://localhost:3000/register?firstName=vcvvc&lastName=vcv&userName=cvv&password=vcv&password=vcv
the codes are
form
<form class="ui form" (ngSubmit)="onSubmit()" #registrationForm="ngForm">
----
----
<button type="submit" class="ui button"> Register</button>
</form>
the service
import { Component } from '#angular/core';
import { User } from '../models/user';
import { RegisterService } from '../services/register.service';
#Component({
selector: 'side-panel',
templateUrl: 'app/components/register.component.html'
})
export class RegisterComponent {
newuser: User = new User();
theText: string;
constructor(private _registerService: RegisterService){
}
onsubmit(){
console.log('form submit clicked..');
this._registerService.sendUser(this.newuser).subscribe(
date =>{
this.newuser = new User();
},
error => console.log(error)
);
}
}
This error occurs when the name of the methods called in an event not matched with the template declaration and inside the class
In your template you have specified onSubmit() as camel case
<form class="ui form" (ngSubmit)="**onSubmit()**" #registrationForm="ngForm">
but inside the class, its not a camelCase "onsubmit()"
onsubmit(){
console.log('form submit clicked..');
this._registerService.sendUser(this.newuser).subscribe(