Angular-material, how to bind an object array - html

I'm dealing with this code which was written by another developer, and I'm not used to angular.
I'm trying to bind the data.order.order_items to an object in the component, to do an additional logic in the component side when the user clicks the button.
<!-- some code -->
<form class="form">
<h4 class="sku-list-title">SKU List</h4>
<mat-slide-toggle
[checked]="isChecked"
(change)="isChecked = $event.source.checked"
class="toggle"
>Edit SKUs</mat-slide-toggle
>
<div
class="item-container"
*ngFor="let element of data.order.order_items"
[(ngModel)]="orderItems"
>
<mat-form-field>
<mat-label>SKU</mat-label>
<input
[value]="element.item.seller_sku"
matInput
tabindex="-1"
[disabled]="true"
/>
</mat-form-field>
<mat-form-field>
<mat-label>New SKU</mat-label>
<input
[placeholder]="element.item.new_seller_sku"
matInput
tabindex="-1"
[disabled]="!isChecked"
/>
</mat-form-field>
<mat-form-field>
<mat-label>Quantity</mat-label>
<input
matInput
maxlength="5"
[value]="element.quantity"
tabindex="-1"
[disabled]="!isChecked"
/>
</mat-form-field>
</div>
</form>
</div>
<!-- some code -->
<div mat-dialog-actions class="actions full-width">
<button mat-flat-button color="warn" (click)="onNoClick()">Cancel</button>
<button
mat-flat-button
color="primary"
(click)="onClick()"
[mat-dialog-close]="closeAnswer"
>
Accept
</button>
</div>
Component side
#Component({
selector: "app-message-dialog",
templateUrl: "./message-dialog.component.html",
styleUrls: ["./message-dialog.component.scss"],
})
export class MessageDialogComponent implements OnInit {
orderItems: any; //This object would bind the order_items
//some code
onClick() {
//some code
this.orderItems //doesn't get the binded data.
How can I bind the data from the data.order.order_items that is updated in that input, to the object this.orderItems?
I tried with the ngModel, but I guess i'm missing something or doing it in the wrong element.
Thanks in advance!

you are binded the data but forgot to display data you can use following syntax {{element }}

you should use the ngModel inside input tag to get the value from corresponding input tag or another option is to use formControl to get the value
NG Model
<input
matInput
maxlength="5"
[value]="element.quantity"
tabindex="-1"
[disabled]="!isChecked"
[(ngModel)]="orderItems"
/>
Form Control
visit this site -> https://angular.io/api/forms/FormControl

Related

HTML & Angular Material disable save button from outside div when form fields are empty

I have the following Angular Material form with the Close and Save buttons in an outside div for design reasons:
<h1 mat-dialog-title>Product Page</h1>
<div mat-dialog-content>
<form [formGroup]="productForm">
<mat-form-field appearance="outline">
<mat-label>Name</mat-label>
<input formControlName="name" required matInput placeholder="Name" style="text-transform:uppercase">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Weight</mat-label>
<input type="number" required formControlName="weight" matInput placeholder="weight">
</mat-form-field>
</form>
</div>
<div mat-dialog-actions [align]="'end'">
<button mat-raised-button color="warn" mat-dialog-close>Close</button>
<button mat-raised-button color="primary" (click)="saveProduct()">Save</button>
</div>
I want to disable the Save button when the form fields are empty but the required parameter isn't working since the buttons are in an outside div. Is there a way to correlate the buttons with the form such that the Save button is disabled until the required fields are filled in?
You can bind it manually :
<button (click)="submit()" [disabled]="!form.valid">Submit</button>
Or you can cheat your way in the modal by providing the form as the main container (yes, it works)
<form [formGroup]="form">
<h1 mat-dialog-title>...</h1>
<div mat-dialog-content>...</div>
<div mat-dialog-actions align="end">
<button type="submit" [disabled]="!form.valid">Submit</button>
</div>
</form>
You could add a validation to your formGroup and use the formGroup to set the button disabled:
on your component:
constructor(fb:FormBuilder
(...)
) {
this.productForm = fb.group({
name: [null, Validators.required]
(...)
})
}
then on your template, adjust the button:
<button mat-raised-button color="primary" [disabled]="productForm.invalid" (click)="saveProduct()">Save</button>
You might as well remove the 'required' from you input (as angular will warn you about this in the console):
<input formControlName="name" matInput placeholder="Name" style="text-transform:uppercase">

How do I add a listener to a search form in Angular material?

I'm working with Angular material and I have a search form. As shown in the following code, I have a button and after a click event on the button, the words written in the search form are given to the searchProductByName method as parameters. I'd like to substitute the button with a listener that, after having written something in the form and having clicked on enter (instead of the button), grabs the things written in the search form and passes them to the searchProductByName method as parameters. Is there a way to do so?
<form class="search-form" >
<mat-form-field class="example-full-width" appearance="fill">
<mat-label >Search</mat-label>
<input #input type="text" ngModel name="name" class="form-control" id="name"
aria-label="Search"
matInput
>
<button (click)="searchProductByName(input.value)" routerLink="/products/searchProduct/by_name" routerLinkActive="active">Go</button>
</mat-form-field>
</form>
Easy way to do that in template is add keyup event to the input:
<form class="search-form" >
<input #input type="text" ngModel name="name" class="form-control" id="name"
(keyup.enter)="searchProductByName(input.value)"
aria-label="Search"
matInput
>
<button (click)="searchProductByName(input.value)" routerLink="/products/searchProduct/by_name" routerLinkActive="active">Go</button>
</mat-form-field>
</form>
Or you can get your input element in component with ViewChild and make listener there.
If the searchPruductByName is a method that is using http request to search from backend, for example - I would suggest to also implement debounce'ing the search as well. Otherwise it would search with each keystroke. A nice elegant way would be to use a debounce decorator. https://medium.com/time-machine/how-to-implement-debounce-decorator-2e963b70cd27
<form class="search-form" >
<input #input type="text" ngModel name="name" class="form-control" id="name"
(input)="searchProductByName($event); onInput($event)"
aria-label="Search"
matInput>
</mat-form-field>
</form>
onInput(event: any) {
console.log(event.target.value);
}
To navigate to link on pressing "Enter" add to constructor Router and then use router to navigate.
constructor(router: Router) {}
onNavigate() {
// other stuff
this.router.navigateByUrl('/products/searchProduct/by_name')
}
<input (keyup.enter)="searchProductByName(input.value); onNavigate()">

formGroup expects a FormGroup instance. Please pass one in. How to fix this error?

My HTML source code as follows,
<p>
<mat-form-field appearance="legacy" [formGroup]="form" (submit)="onFormSubmit()">
<mat-label>Add a List</mat-label>
<input [(ngModel)]="listName" matInput placeholder="Placeholder" formControlName="name" #nameInput fxFlex>
<mat-icon matSuffix class="check" (click)="onFormSubmit()">check</mat-icon>
<mat-icon matSuffix class="clear" (click)="closeForm()">clear</mat-icon>
</mat-form-field>
</p>
when running this code following error shows on the console,
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
how can I fix this error?
Typo ? You wrote:
[formGroup]="form"
It should be:
[formGroup]="myGroup"

Set initial value to a Toggle of a form in Angular Material within HTML

I am working with a simple form:
HTML
<mat-card>
<form (submit)="onAddBet(betForm)" #betForm="ngForm">
<mat-form-field>
<textarea #description="ngModel" matInput rows="6" placeholder="Description" name="description" ngModel
required></textarea>
<mat-error *ngIf="description.invalid">Please enter a Bet Description</mat-error>
</mat-form-field>
<mat-slide-toggle #privacy="ngModel" name="privacy" ngModel>Private</mat-slide-toggle>
<mat-slide-toggle #comments="ngModel" name="comments" ngModel>Allow comments</mat-slide-toggle>
<button mat-raised-button color="primary" type="submit">
CREATE
</button>
</form>
</mat-card>
If I press submit without touching any field of the form I get all the fields empty as it should be expected but I would like to get instead of the status of the form, meaning all the fields as "" but in the fields "privacy" and "comments" as false (boolean) (the default appearance of the toggles is as not marked).
I know that this could be easily done by Typescript from the component following the method:
Typescript
onAddBet(form: NgForm) {
if (!form.value.privacy) {
form.value.privacy = false;
console.log(form.value);
} else console.log(form.value);
if (form.invalid) return;
form.resetForm();
}
But I was wondering if there is any HTML attribute to run the same code avoiding to use Typescript
How could I do it?
You can initialize your ngModel in your HTML by using ngModel with a one-way binding
<mat-slide-toggle #privacy="ngModel" name="privacy" [ngModel]="false">Private</mat-slide-toggle>
<mat-slide-toggle #comments="ngModel" name="comments" [ngModel]="false">Allow comments</mat-slide-toggle>
Then in your component
onAddBet(form: NgForm) {
console.log(form.value);
if (form.invalid) return;
form.resetForm();
}
As per the documentation of slide-toggle you can use [checked]="checked" in HTML.

Form not displaying "required" dialog in Angular 2

I am new to Angular 2. So, I have this form where I created with Angular 2, and bootstrap. So, when you click on the text field and move the mouse else where, the box turns red (which is good). But, when they click on submit button, it when the form is empty, it won't show the "required" dialog. So, please check my code of what I did wrong. Thank you!
I want to show this when they click on a empty form:
Here is the code.
<div class="col-md-8 col-md-offset-2">
<form (ngSubmit)="onSubmit(form)" #form="ngForm">
<div class="form-group">
<label for="content">Content</label>
<input type="text"
id="content"
class="form-control"
ngModel
name="content"
required>
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</div>
Second Part:(TypeScript)
import { Component } from "#angular/core";
import {MessageService} from "./message.service";
import {Message} from "./message.model";
import {NgForm} from "#angular/forms";
#Component({
selector: 'app-message-input',
templateUrl: './message-input.component.html'
})
export class MessageInputComponent {
constructor(private messageService: MessageService) {}
onSubmit(form: NgForm) {
const message = new Message(form.value.content, 'John');
this.messageService.addMessage(message);
form.resetForm();
}
}
I fixed my answer by enabling the default HTML validation. Becuase for some reason in Angular, the default HTML validation is disabled by Angular. So, I enabled it by doing:
<div class="col-md-8 col-md-offset-2">
<form ngNativeValidate (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<label for="content">Content</label>
<input
type="text"
id="content"
class="form-control"
ngModel
name="content"
required>
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
I just add ngNativeValidate in my form tags.