Angular 2 ways binding with one field enabled and the other disabled - html

I am having 2 fields in my angular application. I am using data binding for these two fields because these 2 fields have same data. However, in one of the field I need to enabled it and the other I need to disable it.
I found that both of my field is disabled now when I disabled="true" in one of the fields. Any solutions to only disabled one of the field and the other of the field is enabled?
The following is my source code.
<div class="row">
<div class="col-4">
<label>{{ 'company-info.performance.Red' | translate }}</label>
</div>
<div class="col-2">
<mat-form-field>
<input matInput type="number" min="0" max="100" placeholder="less than %" [(ngModel)]="data.nonprfmCustT1" name="nonprfmCustT1">
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-4">
<label>{{ 'company-info.performance.Amber' | translate }}</label>
</div>
<div class="col-2">
<mat-form-field>
<input matInput [disabled]="true" type="number" placeholder="higher than or Equal %" [(ngModel)]="data.nonprfmCustT1" name="nonprfmCustT1">
</mat-form-field>
<mat-form-field>
<input matInput type="number" min="data.nonprfmCustT1" max="100" placeholder="less than %" [(ngModel)]="data.nonprfmCustT2" name="nonprfmCustT2">
</mat-form-field>
</div>
</div>
Next, how can I set min value of nonprfmCustT2 must be greater than nonprfmCustT1?

Related

Angular Forms change Tab order

For simplicity when building a two column form I built it in two separated divs using flex box. The form however reads from left to right i.e First Name at the top of div one and Surname at the top of div two. If the user uses the tab key to move between inputs the tab key moves down the form rather than across. This was an oversight by me but I was wondering if the tabbing between inputs could be set different from the default. Maybe a picture would help.
So I would like to change it to tab across. How would I do that? Also the actual form is more complicated than shown below so I don't want to rebuild the html.
My HTML
<div fxLayout="row" fxLayout.lt-sm="column" fxLayoutAlign="space-between center">
<div fxFlex="40">
<mat-form-field class="formFieldLeft">
<div class="is-size-7 has-text-grey-light mbxs">First Name</div>
<input matInput formControlName="firstName">
</mat-form-field>
<mat-form-field class="formFieldLeft">
<div class="is-size-7 has-text-grey-light mbxs">Email Address</div>
<input matInput formControlName="email">
</mat-form-field>
<mat-form-field class="formFieldLeft mblg">
<div class="is-size-7 has-text-grey-light mbxs">Company Phone Number</div>
<input matInput formControlName="companyPhoneNumber">
</mat-form-field>
<div fxFlex="60">
<mat-form-field class="formFieldRight">
<div class="is-size-7 has-text-grey-light mbxs">Surname</div>
<input matInput formControlName="lastName">
</mat-form-field>
<mat-form-field class="formFieldRight">
<div class="is-size-7 has-text-grey-light mbxs">Job Title</div>
<input matInput formControlName="jobTitle">
</mat-form-field>
<mat-form-field class="formFieldRight mblg">
<div class="is-size-7 has-text-grey-light mbxs">Mobile Number</div>
<input matInput formControlName="mobilePhoneNumber">
</mat-form-field>
</div>
Add tabIndex like
<input tabindex="3">
<input tabindex="0">
<input tabindex="-1">
<input>
<input tabindex="2">
<input tabindex="1">
see this for more details
You can save active tab index and create separate function on
(keyup)="onKeypressEvent($event)" {
// check does it `tab`
}
chech the key code and depending of where you current tab active change next active tab

Angular 8 Material mat-error shows up on load by default

I am having this weird scenario. my mat-error shows up by default, without even touching the input field. Basically, when I load the page the error message is shown without any user interaction on the input field. I don't have any error messages on the browser console. Can anyone point out what did I miss?
This is my .ts
frmStep3: FormGroup;
matcher = new MyErrorStateMatcher();
// omited unrelated code
this.frmStep3 = this.fb.group({
courseDurationNum: [, [Validators.required, Validators.maxLength(3), Validators.minLength(1)]]
});
return {
frmStep3: this.frmStep3
};
This is my HTML
<form class="form-group-parent p-0" [formGroup]="frmStep3" (ngSubmit)="stepForward()">
<div class="form-group d-inline-block">
<label class="w-100">Choose your course duration<sup>*</sup></label>
<input [errorStateMatcher]="matcher" [maxLength]="3" type="text" class="float-left" matInput
formControlName="courseDurationNum" placeholder="Ex. 1 - 365 Day(s)" />
<mat-error class="w-100 float-left"
*ngIf="frmStep3.get('courseDurationNum').hasError('required') || frmStep3.get('courseDurationNum').invalid">
<strong>Duration</strong> must be between <strong>1 - 365</strong> day(s).
</mat-error>
</div>
</form>
I figured out, I missed wrapping them in from controls in <mat-form-field> tag. Correct code below.
<form class="form-group-parent p-0" [formGroup]="frmStep3" (ngSubmit)="stepForward()">
<div class="form-group d-inline-block">
<mat-form-field>
<label class="w-100">Choose your course duration<sup>*</sup></label>
<input [errorStateMatcher]="matcher" [maxLength]="3" type="text" class="float-left" matInput
formControlName="courseDurationNum" placeholder="Ex. 1 - 365 Day(s)" />
<mat-error class="w-100 float-left"
*ngIf="frmStep3.get('courseDurationNum').hasError('required') || frmStep3.get('courseDurationNum').invalid">
<strong>Duration</strong> must be between <strong>1 - 365</strong> day(s).
</mat-error>
</mat-form-field>
</div>
</form>

How to put two input fealds in anguler align horizonatal?

I need to put two input fields with labels as below.
But In using angular, some data R fields related input not visible. Then, it should be like below.
My code
<div>
<div>
<label i18n="k" *ngIf="model" id="'k'">
<br />
<br />
K:
{{model.k}} </label>
<label i18n="N" *ngIf="model"
id="'N'">
<br />
<br />
N:
{{model.n}} </label>
</div>
<div>
<mat-form-field [formGroup]="DetailForm">
<label *ngIf="isVisible(model.r)">R</label>
<input *ngIf="isVisible(model.r)" matInput formControlName="rate"
[type]="'number'" [placeholder]="'rate'" [required]="false" [readonly]="false" [spaced]="false">
<label>Comment</label>
<input matInput formControlName="c" [type]="'text'" [placeholder]="'comment'" [required]="false"
[readonly]="false" [spaced]="false">
</mat-form-field>
</div>
</div>
But I tried a different way when two input available it shows like below.
need some expert help to resolve this.
I think you need to use 2 different mat-form-fields like this:
<mat-form-field>
<mat-label>Rate</mat-label>
<input matInput placeholder="Placeholder">
</mat-form-field>
<mat-form-field>
<mat-label>Comment</mat-label>
<input matInput placeholder="Placeholder">
</mat-form-field>
Or have a look at this stackblitz, i put a very small demo of the above changes there:
https://stackblitz.com/edit/angular-material-starter-r7khp2

Angular 6 and bootstrap 4: date picker

I have a form which contain a date picker / calender, email, city name and hotel name, I want a user to select a date and enter other fields and submit the data.
This is what I have.
HTML:
<form [formGroup]="angForm" class="form-element">
<div class="form-group">
<label for="dateOfBirth">Date of Birth</label>
<input id="dateOfBirth" name="dateOfBirth" [(ngModel)]="dateOfBirth" type="text" bsDatepicker class="form-control" />
</div>
<div class="form-group form-element_email">
<input type="email" class="form-control info" placeholder="Email" formControlName="email" #email (ngModelChange)="onChange($event)">
</div>
<div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)"
class="alert alert-danger">
<div *ngIf="angForm.controls['email'].errors.required">
Email is required.
</div>
</div>
<div class="input-group mb-3 form-element_city">
<select class="custom-select" id="inputGroupSelect01" #cityName>
<option selected *ngFor="let city of cities" [ngValue]="city.name">{{city.name}}</option>
</select>
</div>
<div class="input-group mb-3 form-element_hotel">
<select class="custom-select" id="inputGroupSelect01" #hotelName>
<option selected *ngFor="let hotel of hotels" [ngValue]="hotel.name">{{hotel.name}}</option>
</select>
</div>
<div class="form-group">
<button type="submit" (click)="addReview(email.value, cityName.value , hotelName.value)" class="btn btn-primary btn-block form-element_btn"
[disabled]="!validEmail">Book</button>
</div>
</form>
This dispalys the following result: wrong one
Instead of that input with date picker , I just want the full calender to be display on the left side ,
Here is what I want . Good one
I tried many solution online I could not be able to solve my problem,
What do I need to change in my code to get the result I want? please Am newbie though, thanks
You can actually provide placement in the element which uses bdDatepicker directive.
Just set this placement property to left value.
Here is example in documentation.
https://valor-software.com/ngx-bootstrap/#/datepicker#placement

Error: Cannot change `multiple` mode of select after initialization

Error image:
<div fxFlex.gt-lg="100" fxFlex="100" *ngIf="requestAction == 'add'">
<div class="pb-1">
<md2-select placeholder="{{'WidgetType'|translate:lang}}" class="input_custom_width"(change)="widgetNode($event.value)" required>
<md2-option *ngFor="let widgetType of widgetTypeAry" [value]="widgetType.value">
{{widgetType.name}}
</md2-option>
</md2-select>
</div>
</div>
<div fxFlex.gt-lg="100" fxFlex="100" *ngIf="fieldsObj['node'] && showRequestAction" >
<div class="pb-1">
<md2-select placeholder="{{'Node'|translate:lang}}" [formControl]="editWidgetForm.controls['nodeId']" [(ngModel)]="nodeId" class="input_custom_width" [(multiple)]="isMultiNode" (change)="nodeChange($event.value)" required>
<md2-select-header>
<md-input-container class="input_custom_width">
<input mdInput type="text" placeholder="{{'Search'| translate:lang}}" [ngModelOptions]="{standalone: true}" [(ngModel)]="searchNode"/>
</md-input-container>
</md2-select-header>
<md2-option *ngFor="let node of nodesAry | filterPipe : searchNode" [value]="node.value">
{{ node.name }}
</md2-option>
</md2-select>
<small *ngIf="editWidgetForm.controls['nodeId'].hasError('required') && editWidgetForm.controls['nodeId'].touched" class="mat-text-warn">{{'nodeReq'|translate:lang}}</small>
</div>
</div>
When I use multiple in select dropdown it works fine but when I use [multiple] it only works in my edit form but not in add form .and it gives above error-Error: Cannot change multiple mode of select after initialization.help me to sort out this.
There is a very ugly workaround for this problem, warp your mat-select in a *ngif=true, and create a duplicate with the multiple property, wrapped in a *ngif=!true just beneath it