Angular binding for datetime input field min and max value - html

I don't know if there is a way to bind variable values from .ts file to input value, min and max properties.
I've tried many ways, but none seems to be working.
I have two-way biding to get the value from input field [(ngModel)]="transferPoint.arrivalTime, but I need to set min and max properties to certain values.
This is not working: min='{{flight.departureTime}}'
This is my html file
<h1 mat-dialog-title>ADD NEW TRANSFER POINT</h1>
<div mat-dialog-content>
<mat-form-field>
<input type="datetime-local" id="arrival-time" name="arrival-time" value="{{flight.departureTime}}" min="{{flight.departureTime}}"
max="{{flight.arrivalTime}}" matInput [(ngModel)]="transferPoint.arrivalTime" placeholder="Arrival time">
</mat-form-field>
<br>
<mat-form-field>
<input type="datetime-local" id="departure-time" name="departure-time" value="2018-06-12T19:30" min="2018-06-07T00:00"
max="2018-06-14T00:00" matInput [(ngModel)]="transferPoint.departureTime" placeholder="Departure time">
</mat-form-field>
<br>
<mat-form-field>
<input matInput [(ngModel)]="transferPoint.countryAndCity" placeholder="Country and City">
</mat-form-field>
</div>
<div mat-dialog-actions>
<button class="submitbtn" mat-raised-button (click)='addTransferPoint()'>ADD</button>
<button class="cancelbtn" mat-raised-button mat-dialog-close>CANCEL</button>
</div>
and here is my .ts file
export class AddTransferPointComponent implements OnInit {
errorMessage: string;
flightId: any;
flight: FlightDTO;
transferPoint: TransferPointDTO = new TransferPointDTO();
constructor(#Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<any>,
private transferPointService: TransferService,
private flightService: FlightService) { }
ngOnInit() {
this.flightId = this.data.flight;
}
getFlight() {
this.flightService.getFlight(this.flightId).subscribe(
data => {
this.flight = data;
}
)
}
addTransferPoint() {
this.transferPoint.flightId = this.flightId;
this.transferPointService.createTransferPoint(this.transferPoint).subscribe(
data => {
this.dialogRef.close();
location.reload();
},
error => {
console.log(error);
this.errorMessage = error.error.message;
}
);
}
}

You can use property binding (see also https://angular.io/guide/template-syntax):
<input type="datetime-local" id="arrival-time" name="arrival-time" [value]="flight.departureTime" [min]="flight.departureTime" [max]="flight.arrivalTime" matInput [(ngModel)]="transferPoint.arrivalTime" placeholder="Arrival time">

I ran into a similar problem trying to do a matInput type="datetime-local". When I debugged it it looks like what goes into the [min] directive needs to be formatted into a string it can understand.... Essentially pass it a string in this format:
YYYY-MM-DDTHH:MM
Perhaps not the most optimal, but in my case when I switched my data like this it works
var month = this.formatDate(min.getMonth() + 1);
var day = this.formatDate(min.getDate());
this.minDate = min.getFullYear() + "-" + month + "-" + day + "T00:00";
where formatDate is:
private formatDate(nmbr: number): string {
var date = nmbr + "";
date = (date.length < 2) ? "0" + date : date;
return date;
}
Then I can use it in the directive:
<input id="eventTime" matInput type="datetime-local" [min]="minDate" name="eventTime">

Related

patchValue not working when using [[ngModel]]

So when I open an item editor dialog, I want to be able to put some default values that I retrieve from the specific item I selected. This all worked up until I added [[ngModel]] in each of the fields. In fact, it still works when I remove it. I want to be able to do it again without removing the ngModel as I heavily depend on it in my code.
This is my HTML
<div mat-dialog-content class="formCentered">
<form [formGroup]="form">
<mat-form-field class="inputBox">
<mat-label>Scanner</mat-label>
<input matInput formControlName="scannerName" [(ngModel)]="data.scanName" maxlength="50">
</mat-form-field>
<mat-form-field class="inputBox">
<mat-label>Calibration Price</mat-label>
<input matInput formControlName="calibrationPrice" [(ngModel)]="data.caliPrice" maxlength="50">
</mat-form-field>
<mat-form-field class="inputBox">
<mat-label>Calibration Description</mat-label>
<input matInput formControlName="calibrationDescription" [(ngModel)]="data.caliDescription" maxlength="50">
</mat-form-field>
</form>
</div>
<div mat-dialog-actions class="alignRight">
<button mat-button class="confirmationButton" (click)="onNoClick()" class="confirmationButton">Cancel</button>
<button mat-button class="confirmationButton" [mat-dialog-close]="data" cdkFocusInitial class="confirmationButton">Save</button>
</div>
And this is my part of the ts for this
dialogRef.componentInstance.form.patchValue({
scannerName: cal.scannerName, // scannerName is the old value (unedited)
calibrationPrice: cal.calibrationPrice, // calibrationPrice is the old value (unedited)
calibrationDescription: cal.calibrationDescription // calibrationDescription is the old value (unedited)
});
Any idea on how I can achieve that?
It's not a good practice merge reactive forms with ngModel.
You can remove all of the [(ngModel)] in the html, and subscribe to the form changes. Then, when some field of the form change, the subscription would change your varaibles as well.
Add in your ts code something like this:
// after you have inicialized your form
this.form.get('scannerName').valueChanges
.subscribe((val: any) => {
//this.data.scanName = this.form.get('scannerName').value;
this.data.scanName = val
});
this.form.get('calibrationPrice').valueChanges
.subscribe((val: any) => {
//this.data.calibrationPrice= this.form.get('calibrationPrice').value;
this.data.calibrationPrice= val
});
this.form.get('calibrationDescription').valueChanges
.subscribe((val: any) => {
//this.data.calibrationDescription= this.form.get('calibrationDescription').value;
this.data.calibrationDescription= val
});
You can't add NgModel in formGroup.
You have to define the formControl
example:
form = new FormGroup({
scannerName: new FormControl(''),
calibrationPrice: new FormControl(''),
calibrationDescription: new FormControl(''),
})
If you want set default value, you have to set value in new FormControl like this:
form = new FormGroup({
scannerName: new FormControl('test'),
calibrationPrice: new FormControl('value'),
calibrationDescription: new FormControl(someValue),
})
it's seems that you want change data variable, you could do this:
this.data = this.form.value

Set default value of form field based on the dropdown selected by the user

I have a form where a user has to enter a bunch of info. I am using mat-select for one dropdown field. What I'm trying to do is set the default value of another form field based on the drop down selected by the user. How can I achieve this. Thanks in advance for your help.
Here is my template:
<form [formGroup]="newFormGroup" (ngSubmit)="submit()">
<div f>
<mat-form-field appearance="fill" >
<mat-label>Animal Sound</mat-label>
<input matInput type="text" formControlName="animalSound" [(ngModel)]="sound" name="animalSound" class="form-control" id="animalSound">
</mat-form-field>
<mat-form-field appearance="fill" style="width: 10%;">
<mat-label>Animal</mat-label>
<mat-select formControlName="animal" [(ngModel)]="selectedValue">
<mat-option *ngFor="let animal of animals" [value]="animal.value">
{{animal.value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</form>
Here is my ts code:
selectedValue: string;
sound = 'bark';
animals: AnimalType[] = [
{value: 'Cat' },
{value: 'Dog'} ];
newFormGroup = new FormGroup({
animalSound: new FormControl('', Validators.required),
animal: new FormControl('', Validators.required)
});
So for example, If user selects dog, I want set the default value for the animal sound field as bark.
create a service which has a behavior subject;
#Injectable({provideIn: 'root'})
class DropdownService {
value = new BehaviourSubject('Default')
setValue(value: string){
this.value.next(value);
}
getValue() {
return this.value.asObservable();
}
}
set value on dropdown component
then get value in form component
constructor(private dropdownService: DropdownService) {}
ngOnInit(){
// after your form initiated
this.dropdownService.getValue().subscribe(value => {
this.form.controls.field.setValue(value)
});
}

Formatting an input value as currency in an Angular reactive form

I'm trying to format a value as a currency in a nested reactive angular form.
I have an order that has multiple oder items, and I'm creating the form like this:
this.orderForm = this.fb.group({
id: new FormControl({ value: order.id, disabled: true }),
orderItems: this.fb.array([])
});
get orderItems() {
return this.orderForm.get('orderItems') as FormArray;
}
And my html:
<form [formGroup]="orderForm">
<div formArrayName="orderItems">
<div *ngFor="let controls of orderItems.controls;let i=index" [formGroupName]="i">
<mat-form-field>
<mat-label>Description</mat-label>
<input matInput formControlName="description">
</mat-form-field>
<mat-form-field>
<mat-label>Total</mat-label>
<input type="text" matInput formControlName="total">
</mat-form-field>
</div>
</div>
</form>
How do I format the Total as a currency? I can't do
[value]="total | currency"
As total isn't a variable, I've also tried
[value]="orderItems[i].get('total').value | currency"
but that just gives me:
cannot read property '0' of undefined
This should fix your code:
[value]="orderItems.value[i].total | currency"
The value of the the orderItems is the array in this scenario.

How to fetch data from database to textbox typescript

How to fetch data from database to textbox typescript? My Get function is working it display on console but not on textbox.
export class ProfileComponent implements OnInit {
Profile: Profile = new Profile;
constructor(
private ProfileService: ProfileService,
private Security: Security){
}
ngOnInit() {
this.GetProfileByID(this.Security.UserID);
}
GetProfileByID(UserID: any) {
this.ProfileService.GetProfileByID(UserID).then(
(response) => {
console.table(response.Body)
}
)
}
}
Here's my html
`
<form #updateForm="ngForm">
<div class="input-container mb-3">
<div class="col-12">
<label>* Name</label>
<input name="name" #name="ngModel" id="TACName" type="text" [(ngModel)]="Profile.Name" pInputText required/>
<div class="errortxt" [hidden]="name.valid || name.pristine" class="alert alert-danger">
<div class="errortxt" [hidden]="!name.hasError('required')"> Name is Required!</div>
</div>
</div>
</div>
<button class="ui-button-raised submit-btn" [disabled]="!updateForm.valid || !Agreement" pButton label="SAVE" type="submit" (click)="Save(updateForm)"></button>
</form>
`
here's the result on console
According the output result in the console...
GetProfileByID(UserID: any) {
this.ProfileService.GetProfileByID(UserID).then(
(response) => {
this.Profile.Name = response.Body.Name;
}
)
}
There is a typo, you should use new Profile() instead of new Profile.
Really recommending to not use [(ngModel)]. Use FormGroup instead and then after receiving your response from service, use FormGroup.get(controlName: string).patchValue. That will fix your issue for sure.

Md-dialog close after notification

I have dialog box where user can enter data and after clicking on "create", my dialog box gets close and user gets notification. I want to close my dialog box after user get notification and if user enters wrong data, user should get notification for that too and dialog box should not get close.
Currently, everything is working properly but I want my dialog box should disappear after notification (toster service).
Can anyone help me with this thing so that my dialog box will stay till i get notification for success and also for error?
exhibit.component.ts (main component)
createExhibit(event: any) {
let context = this;
this.createDialogRef = this.dialog.open(CreateExhibitDialogComponent, { width: '45em', data: {} });
this.createDialogRef.afterClosed().subscribe(
(newExhibit: Exhibit) => {
if (newExhibit.latitude) { newExhibit.latitude = newExhibit.latitude.toString().replace(/,/g, '.'); }
if (newExhibit.longitude) { newExhibit.longitude = newExhibit.longitude.toString().replace(/,/g, '.'); }
if (newExhibit) {
this.exhibitService.createExhibit(newExhibit)
.then(
() => {
this.toasterService.pop('success', this.translate('exhibit saved'));
setTimeout(function () {
context.reloadList();
}, 1000);
}
).catch(
error => this.toasterService.pop('error', this.translate('Error while saving'), error)
);
}
this.createDialogRef = null;
}
);
}
createExhibit.component.ts
<h1 md-dialog-title>{{ 'create exhibit' | translate }}</h1>
<md-dialog-content>
<form id="new-exhibit-form">
<md-input-container>
<input mdInput placeholder="{{ 'name' | translate }}" [(ngModel)]="exhibit.name" name="name" required>
</md-input-container>
<md-input-container>
<textarea
mdInput
mdTextareaAutosize
#autosize="mdTextareaAutosize"
placeholder="{{ 'description' | translate }}"
[(ngModel)]="exhibit.description"
name="desc"></textarea>
</md-input-container>
<div layout="row" layout-align="start center" flex>
<md-icon _ngcontent-c7="" class="mat-icon material-icons centered" role="img" aria-hidden="true">search</md-icon>
<md-input-container>
<input mdInput placeholder="search for location" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="form-control" #search [formControl]="searchControl">
</md-input-container>
<md-input-container>
<input (blur)="updateMap()" mdInput type="number" min="-90" max="90" step="0.000001"
placeholder="{{ 'latitude' | translate }}" [(ngModel)]="exhibit.latitude" name="lat">
</md-input-container>
<md-input-container>
<input (blur)="updateMap()" mdInput type="number" min="-180" max="180" step="0.000001"
placeholder="{{ 'longitude' | translate }}" [(ngModel)]="exhibit.longitude" name="long">
</md-input-container>
<md-select class="align-right" placeholder="{{ 'status' | translate }}" [(ngModel)]="exhibit.status" name="status">
<md-option *ngFor="let statusOption of statusOptions" [value]="statusOption">{{ statusOption | translate }}</md-option>
</md-select>
</div>
<agm-map (mapClick)="selectLocation($event)" [zoom]=15 [latitude]="lat" [longitude]="lng">
<agm-marker [iconUrl]="'../../../images/map-marker.png'" *ngIf="exhibit.longitude && exhibit.latitude" [latitude]="exhibit.latitude" [longitude]="exhibit.longitude"></agm-marker>
</agm-map>
</form>
</md-dialog-content>
<md-dialog-actions align="end">
<button md-dialog-close md-raised-button>
{{ 'cancel' | translate }}
<md-icon>cancel</md-icon>
</button>
<button md-raised-button [disabled]="!exhibit.isValid()" color="primary" (click)="dialogRef.close(exhibit)">
{{ 'create' | translate }}
<md-icon>add_circle</md-icon>
</button>
</md-dialog-actions>
how to do this?
As windmaomao stated you need to manulally call dialog close() method. Material Dialog component proivide Observable only from afterClose() or beforeClose() and these methods listen to data passed through close() method. The close() method closes the dialog ofcourse what is not our expectation. You need to implement your own communication system between component and dialog build with kind of Observable or EventEmitter.
I have prepared simplified solution of your problem. The trick is you can obtain reference to any field or method of your dialog component with 'componentInstance' getter.
Dialog component
import {Component, EventEmitter, OnInit} from '#angular/core';
import {MatDialogRef} from "#angular/material";
#Component({
selector: 'app-simple-dialog',
template: `<h2 mat-dialog-title>Entering some data</h2>
<mat-dialog-content>Is data OK?</mat-dialog-content>
<mat-dialog-actions>
<button mat-button (click)="actionNo()">No</button>
<button mat-button (click)="actionYes()">Yes</button>
</mat-dialog-actions>`,
styleUrls: ['./simple-dialog.component.css']
})
export class SimpleDialogComponent implements OnInit {
private _action: EventEmitter<boolean> = new EventEmitter<boolean>();
answer = this._action.asObservable();
constructor(public dialogRef: MatDialogRef<SimpleDialogComponent>) { }
actionYes() {
this._action.next(true);
}
actionNo() {
this._action.next(false);
}
closeDialog() {
this.dialogRef.close();
}
ngOnInit() {
}
}
And HTML template excerpt code to include in your main component:
<button (click)="openDialog()">Open Dialog</button>
The code of openDialog() method:
openDialog() {
let dialogRef = this.dialog.open(SimpleDialogComponent);
dialogRef.componentInstance.answer.subscribe( answer => {
console.log('Answer from Dialog: ' + answer);
switch(answer) {
case true:
console.log('Data is OK. Closing dialog');
//do some complicated stuff
dialogRef.componentInstance.closeDialog();
//can be simple: dialogRef.close();
break;
case false:
console.log('Data is not OK. Not closing dialog. Show some toaster');
break;
}
}
)
}