Add dynamic component in the DOM - javascript

I have a project in Angular in which I have created a dialog with several fields for a component. What I want is to take advantage of this dialog for other components, but the amount of data varies.
This is my dialog.component.html:
<div class="dialog-container">
<mat-form-field>
<input matInput placeholder="Name" [(ngModel)]="data.name">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Phone" [(ngModel)]="data.phoneNumber">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Email" [(ngModel)]="data.email">
</mat-form-field>
</div>
I want to know if it is possible to create only one mat-form component and display as many as necessary, passing it the number of fields that I want to generate.
This is what I want the dialog.component.html to contain, to achieve the same as above (I don't know if this is possible):
<div class="dialog-container">
<mat-form-field>
<input matInput placeholder={{place}} [(ngModel)]={{data}}>
</mat-form-field>
</div>
From only one mat-form-field is it possible to show the same result as the first example?

You could create a custom directive :
import { Directive, Input } from '#angular/core';
import { NgForOf } from '#angular/common';
#Directive({
selector: '[ngFor][ngForRepeat]'
})
export class NgForRepeat<T> extends NgForOf<T> {
#Input() set ngForRepeat(repeat: number) {
this.ngForOf = new Array(repeat >= 0 ? repeat : 0);
}
}
And use it as follow in you template :
<ng-container *ngForRepeat="3">
<mat-form-field>
<input matInput placeholder={{place}} [(ngModel)]={{data}}>
</mat-form-field>
</ng-container>

Related

mat-autocomplete the option value does not appear correctly in IOS device

When I select the first option in the dropdown, the option is not reflected in the field. When I select the second option then first option value appears and when selects third the second option value appears. Any suggestions as to what the problem is in my code?
This is happening only on iOS devices.Its working fine on Android and Desktop.
emailDomains = AvailableDomains.emailDomains;
export const AvailableDomains = {
emailDomains: [
"hotmail.com",
"gmail.com",
"yahoo.com",
"outlook.com"
]
}
<mat-form-field appearance="outline" class="textbox mat-form-field-invalid">
<span class="iconError icon-alert" aria-hidden="false" aria-label="Error"></span>
<mat-label>Email</mat-label>
<input matInput placeholder="Enter" formControlName="email" type="email" [matAutocomplete]="emailAutoComplete" #email>
<mat-autocomplete #emailAutoComplete="matAutocomplete" panelWidth="auto">
<mat-option *ngFor="let emailDomain of (email.value.endsWith('#') && email.value.split('#').length == 2 ? emailDomains : [])" [value]="email.value + emailDomain">#{{emailDomain}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
I have some auto-complete code that does work on IOS. I compared the two and the difference I see is that I am using (optionSelected) on the mat-autocomplete tag instead of (onSelectionChange) on the mat-option tag. Try it and see.
<mat-form-field appearance="outline" class="textbox mat-form-field-invalid">
<span class="iconError icon-alert" aria-hidden="false" aria-label="Error"></span>
<mat-label>Email</mat-label>
<input matInput placeholder="Enter" formControlName="email" type="email" [matAutocomplete]="emailAutoComplete" #email>
<mat-autocomplete #emailAutoComplete="matAutocomplete" panelWidth="auto" (optionSelected)="updateForm($event,emailDomain)">
<mat-option *ngFor="let emailDomain of (email.value.endsWith('#') && email.value.split('#').length == 2 ? emailDomains : [])" [value]="email.value + emailDomain">#{{emailDomain}}
</mat-option>
</mat-autocomplete>
</mat-form-field>

show component error in mat-from-field angular 9

i want to create a share component for show error in angular material .
this is my share component pfa-share-error:
<mat-error *ngIf="fieldErrors(fieldName).required && fieldErrors(fieldName)">
Reqierd
</mat-error>
<mat-error *ngIf="fieldErrors(fieldName).touched && fieldErrors(fieldName)">
Reqierd
</mat-error>
<mat-error *ngIf="fieldErrors(fieldName).pattern && fieldErrors(fieldName)">
Reqierd
</mat-error>
and i using this in the my form :
<mat-form-field appearance="outline">
<mat-label>{{ "COUNTEY.NAME" | translate }}</mat-label>
<input formControlName="name" matInput />
<pfa-share-error [form]="addCountryFG" field="name"></pfa-share-error>
</mat-form-field>
but it show like this in my form when error occure :
i want show that like this :
now how can i solve this problem ????
You may try something like following:
In your main HTML file:
<mat-form-field appearance="outline">
<mat-label>{{ "COUNTEY.NAME" | translate }}</mat-label>
<input formControlName="name" matInput />
<mat-error>
<pfa-share-error [form]="addCountryFG" field="name"></pfa-share-error>
</mat-error>
</mat-form-field>
In your shared component pfa-share-error:
<ng-container *ngIf="fieldErrors(fieldName).required && fieldErrors(fieldName)">
This field is required and cannot be empty
</ng-container>

Angular 2 way number binding converting to string from input

Any time I enter a number into an input that is 2 way bound to my object the value is converted to a string.
How can I force it or convert it to be a number?
It seems like it should be very simple and yet I have struggled to find an elegant solution.
I saw this solution of using a function to convert it but I don't see how that would work for 2 way data binding.
convert string to number angular 2 one way binding
<div class="row">
<mat-form-field class="custom-control">
<input type="number" matInput class="custom-control" [(ngModel)]="mpv.baseFare" required placeholder="Base Fare">
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="custom-control">
<input type="number" matInput class="custom-control" [(ngModel)]="mpv.mileageRate" required placeholder="Mileage Rate">
</mat-form-field>
</div>
mpv is an object of class VehicleType I have my VehicleType class set up as follows. The number types are completely ignored, I guess because it is at run time so just non typed javascript.
export class VehicleType {
baseFare: number;
mileageRate: number;
}
UPDATE - CURRENT HACKY SOLUTION:
onSave(vehicleType: VehicleType) {
// Hack to convert string to number
vehicleType.bags = +vehicleType.bags;
vehicleType.baseFare = +vehicleType.baseFare;
vehicleType.mileageRate = +vehicleType.mileageRate;
vehicleType.passengers = +vehicleType.passengers;
this.vehicleTypeService.updateVehicleType(vehicleType.id, vehicleType).subscribe(result => {
It turns out that the order of the attributes on a matInput mater. This issue does not occur on a standard input only a matInput.
Does not work:
<input type="number" matInput class="custom-control" [(ngModel)]="mpv.baseFare" required placeholder="Base Fare">
Works:
<input matInput type="number" class="custom-control" [(ngModel)]="mpv.baseFare" required placeholder="Base Fare">
If you want to be able to modify the value when ngModel sets a new value then you're most likely looking at creating a get and set function. Example,
<div class="row">
<mat-form-field class="custom-control">
<input type="number" matInput class="custom-control" [(ngModel)]="baseFare" required placeholder="Base Fare">
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="custom-control">
<input type="number" matInput class="custom-control" [(ngModel)]="mileageRate" required placeholder="Mileage Rate">
</mat-form-field>
</div>
get baseFare(): number {
return mpv.baseFare;
}
set baseFare(value: any) {
mpv.baseFare = pareseInt(value, 10);
}
get mileageRate(): number {
return mpv.mileageRate;
}
set mileageRate(value: any) {
mpv.mileageRate = pareseInt(value, 10);
}
That should do the job.
Update: you could just have value as any or both as any since you know the return type will be a number.

Quarterly date picker

I am looking for a quarterly date picker, preferably using Angular, like something shown below:
Both Bootstrap and (Angular) Material dont seem to offer this functionality.
Is there any other existing frameworks/libraries that could offer this?
Why not use, e.g. an autocomplete in material, some like
<form class="example-form">
<mat-form-field class="example-full-width">
<input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<button mat-icon-button (click)="change(-1)"><</button>{{year}}<button mat-icon-button (click)="change(1)">></button>
<mat-option *ngFor="let option of options;let i=index" [value]="option.value">
{{option.value}}<span *ngFor="let month of option.months">{{month}}</span>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
options: any[] = [
{value:1,months:['Ene','Feb','Mar']},
{value:2,months:['Apr','May','Jun']},
{value:3,months:['Jul','Ago','Sep']},
{value:4,months:['Oct','Nov','Dec']}
];
year=new Date().getFullYear()
change(inc)
{
this.year+=inc
}
see a fool example in stackblitz

How to share the data up from transcluded content angular 4

I have a generic modal
<div class="modal-header">
<h1 mat-dialog-title [innerHTML]="data.title"></h1>
</div>
<div mat-dialog-content>
<ng-content></ng-content>
</div>
<mat-dialog-actions>
<button></button>
</mat-dialog-actions>
and i have the content for the modal
<modal>
<form #form="ngForm" (ngSubmit)="addNewPerson(person)">
<mat-form-field>
<input type="text" [(ngModel)]="person.firstName" name="firstName"
placeholder="First Name" matInput required>
</mat-form-field>
</form>
</modal>
How can i send the data from this form in generic modal component? Thanks a lot
Sending data from child up to generic modal with #Output() doesn't work in this case. Also will be nice to see how to send data down in component from the generic modal, as we can do with #Input() in simple components hierarchy.
You can add a custom directive that grabs a reference to the NgForm directive
<form myFormDirective #form="ngForm" (ngSubmit)="addNewPerson(person)">
#Directive({
selector: '[myFormDirective]',
})
export class MyFormDirective {
constructor(form:NgForm, myService:MyService) {
console.log(form.value);
myService.theForm = form;
}
}
then you can use a shared service to pass the NgForm reference along and on demand read the form value from theForm.value or initiate some other actions.;

Categories