Dynamically update FormBuilder group inputs - javascript

When FormGroup instance is created it creates a FormGroup object that has controls and values.
I have one form that has different controls, they activate depending on what type of form was chosen.
The problem is that formGroup instance stays same, so my controls are not read, and I am getting an error that controls are not found.
I will include task.component.ts file where i update a task and read values into input fields:
upateTaskForm(taskBody, taskType) {
this.formActive = true;
if (this.task === 'medication') {
console.log(this.formGroup + "MEDICATION FORMGROUP");
this.formGroup = this.formBuilder.group({
title: taskBody.title,
instructions: taskBody.instructions,
repeatWeekDay: [null],
medication: this.formBuilder.group({
name: taskBody.medication[0].name,
dose: this.formBuilder.group({
quantity: taskBody.medication[0].quantity,
unit: taskBody.medication[0].dose.unit
}),
method: taskBody.medication[0].method,
notes: taskBody.medication[0].notes
})
});
// Reading Form populates from the formbuilder
} if (this.task === 'reading') {
console.log(this.formGroup + "READING FORMGROUP");
this.formBuilder.group({
title: taskBody.title,
reading: this.formBuilder.group({
measureType: taskBody.reading[0].measureType,
measureValue: taskBody.reading[0].measureValue,
measureUnits: taskBody.reading[0].measureUnits,
}),
instructions: taskBody.instructions,
});
} else if (this.task === 'symptoms') {
this.formGroup = this.formBuilder.group({
title: [null, Validators.required],
instructions: [null]
});
}
}
This is HTML code for the task.component.html
formGroup is an instance of the form and, once its submited values are stored in formGroup.value
formGroup is
Copy from library
Search Tasks in Library
Name
Event
Medication
<label class="form-check-label d-block d-md-inline">
<input type="radio" class="form-check-input" (click)="setTask('reading')" name="event" [checked]='task==="reading"' value="measurement"> Measurement</label>
<label class="form-check-label d-block d-md-inline">
<input type="radio" class="form-check-input" (click)="setTask('record-symptoms')" name="event" [checked]='task==="symptoms"'
value="symptoms"> Record Syptoms</label>
</div>
</div>
<!-- Medication Form -->
<div id="medicationForm" formArrayName="medication" *ngIf="task==='medication'">
<div class="form-group row mx-auto mt-4" formArrayName="dose">
<label class="col-md-3" for="response">Dose</label>
<input type="number" name="number" class="form-contol col-md-6 mr-4" placeholder="Quantity" formControlName="quantity">
<select class="col" formControlName="unit">
<option default>Tablet(s)</option>
<option>Pill</option>
<option>Liquid</option>
</select>
</div>
<div class="form-group row mx-auto mt-4">
<label class="col-md-3"></label>
<input type="text" class="form-contol col-md-6 mr-4" placeholder="Unit / eg Melformin 500mg" formControlName="name">
<select class="col" formControlName="method">
<option default>Oral</option>
<option>IV</option>
<option>Tropical</option>
<option>ophthalmic</option>
</select>
</div>
<div class="form-group row mx-auto mt-4">
<label for="notes" class="col">Notes</label>
<input type="text" name="notes" class="form-control col-md-9 ml-auto" placeholder="Take before bed, take before eating" formControlName="notes">
</div>
</div>
<!-- Measurement Form -->
<div id="measurementForm" *ngIf="task==='reading'" formArrayName="reading" >
<div class="form-group row mx-auto mt-4">
<label class="col-md-3">Measurement Type</label>
<input type="text" class="form-contol col" placeholder="Heart_rate, Systolic, Diastolic, Weight" formControlName="measureType">
</div>
<div class="form-group row mx-auto mt-4">
<label class="col-md-3" for="response">Measurement Value</label>
<input type="number" class="form-contol col-md-6 mr-4" placeholder="Value of the measurement" formControlName="measureValue">
<select class="col" formControlName="measureUnits">
<option default>KG</option>
<option>LBS</option>
<option>mmHg</option>
<option>MG/DL</option>
<option>MMOL</option>
<option>STEPS</option>
</select>
</div>
</div>
<div class="form-group row mx-auto">
<label class="col" for="instructions">Instructions</label>
<input class="form-control col-md-9 ml-auto" type="text" formControlName="instructions" placeholder="Anything to say to the patient">
</div>
<div class="modal-footer my-3">
<button class="d-none d-md-block btn btn-secondary btn-sm btn-md-lg mr-auto ml-md-4" data-dismiss="modal">CANCEL</button>
<button class="d-md-none btn btn-secondary btn-sm btn-md-lg mr-auto ml-md-4" data-dismiss="modal">×</button>
<button type="submit" class="d-none d-md-block btn btn-primary btn-sm btn-md-lg mr-md-4">CREATE TASK</button>
<button class="d-md-none btn btn-primary btn-sm btn-md-lg mr-md-4">OK</button>
</div>
</form>
enter image description here

You only need to use the FormBuilder class once, to get an instance of FormGroup. After that, if you need to dynamically add or remove FormControls, you can use the addControl and removeControl methods.

Related

Dynamic clear form Validation not Working inside FormGroup of FormArray angular 11

I'm trying to clear my validation for that particular group based on user input.I have tried like this but not work for me.
this.myForm = this.fb.group({
questions: this.fb.array([
this.fb.group({
question_name: ['', Validators.required],
type: ['', Validators.required],
point: ['', Validators.required],
no_of_answer: [''],
option: this.fb.array([]),
right_answer: ['', Validators.required],
}),
]),
});
this.type = [
{ name: 'Multiple choice choose one( radio)', type: 'radio' },
{ name: 'Multiple choice choose many', type: 'checkbox' },
{ name: 'True / False(radio)', type: 'radio' },
{
name: 'Fill in the blank single input',
type: 'singleInput',
},
{
name: 'Fill in the blank multiple choice',
type: 'multipleInput',
},
];
// when question type is selected
type_selected(comp) {
const value = comp.get('type').value;
switch (value) {
case 'radio':
const control = comp.controls['right_answer'] as FormControl;
control.clearValidators();
break;
case 'checkbox':
console.log('option required');
break;
case 'singleInput':
console.log('Answer Required');
break;
case 'multipleInput':
console.log('Multiple Answer Required');
break;
default:
console.log('');
}
}
component.html
<div class="container-fluid">
<div *ngIf="new_created; else existing">
<div class="container-fluid mt-3">
<form [formGroup]="myForm" (ngSubmit)="create_company_fun()">
<ng-container formArrayName="questions">
<div
class="row"
*ngFor="let comp of questionFormArr.controls; let i = index"
>
<p-divider align="center" class="mt-3">
<div class="p-d-inline-flex p-ai-center">
<i class="pi pi-question p-mr-2"></i>
<b>Question {{ i + 1 }} </b>
</div>
</p-divider>
<ng-container [formGroupName]="i">
<div class="col-12 col-md-9 mt-5">
<span class="p-float-label w-100">
<input
type="text"
id="inputtext"
class="form-control"
pInputText
formControlName="question_name"
/>
<label for="inputtext">Question Name</label>
</span>
</div>
<div class="col-12 col-md-3 mt-5 d-flex">
<div>
<button
pButton
pRipple
type="button"
icon="pi pi-plus"
(click)="addNewQuestion()"
class="p-button-rounded p-button-success"
></button>
</div>
<div style="margin-left: 1rem">
<button
pButton
pRipple
type="button"
icon="pi pi-minus"
(click)="deleteQuestion(i)"
class="p-button-rounded p-button-danger"
></button>
</div>
</div>
<div class="col-12 col-md-4 mt-5">
<span class="p-float-label w-100">
<input
type="text"
id="inputtext"
class="form-control"
pInputText
formControlName="point"
/>
<label for="inputtext">Points</label>
</span>
</div>
<div class="col-12 col-md-4 mt-5">
<span class="p-float-label w-100">
<p-dropdown
inputId="dropdown"
[autoDisplayFirst]="false"
[options]="type"
[style]="{ minWidth: '100%' }"
optionLabel="name"
optionValue="type"
formControlName="type"
(onChange)="type_selected(comp)"
></p-dropdown>
<label for="dropdown">Type</label>
</span>
</div>
<div
class="col-12 col-md-4 mt-5"
*ngIf="comp.get('type').value == 'multipleInput'"
>
<span class="p-float-label w-100">
<input
type="text"
id="inputtext"
class="form-control"
pInputText
formControlName="no_of_answer"
/>
<label for="inputtext">Number of Answer</label>
</span>
</div>
<ng-container
*ngIf="
comp.get('type').value == 'radio' ||
comp.get('type').value == 'checkbox'
"
>
<div class="col-12" formArrayName="option">
<div
class="row"
*ngFor="
let project of comp.get('option')['controls'];
let j = index
"
>
<div class="col-12 col-md-9 mt-5">
<span class="p-float-label w-100">
<input
type="text"
id="inputtext"
class="form-control"
pInputText
[formControlName]="j"
/>
<label for="inputtext">Option {{ j + 1 }} </label>
</span>
</div>
<div class="col-12 col-md-3 mt-5 d-flex">
<div>
<button
pButton
pRipple
type="button"
icon="pi pi-plus"
(click)="addNewOption(comp.get('option'))"
class="p-button-rounded p-button-success"
></button>
</div>
<div style="margin-left: 1rem">
<button
pButton
pRipple
type="button"
icon="pi pi-minus"
(click)="deleteOption(comp.get('option'), j)"
class="p-button-rounded p-button-danger"
></button>
</div>
</div>
</div>
</div>
</ng-container>
<div
class="col-12 col-md-9 mt-5"
*ngIf="comp.get('type').value !== 'multipleInput'"
>
<span class="p-float-label w-100">
<input
type="text"
id="inputtext"
class="form-control"
pInputText
formControlName="right_answer"
/>
<label for="inputtext">Right Answer</label>
</span>
</div>
<div class="col-12 col-md-3 mt-5">
<button class="btn btn-primary" [disabled]="myForm.invalid">
Create
</button>
</div>
</ng-container>
</div>
</ng-container>
</form>
</div>
</div>
<ng-template #existing>
<app-add-from-existing-question></app-add-from-existing-question>
</ng-template>
</div>
What I want is, If the user selected single-input I want to hide options and their validation.
All Works fine except validation. I'm unable to clear or set validation inside my formgroup
Thanks for the StackBlitz link, however, the details are incomplete there and is throwing an error. Please update the link for future purposes.
Straight from the docs, please try using updateValueAndValidity() which recalculates the value and validation status of the control. Call it on your control constant variable as- control.updateValueAndValidity();
Link: https://angular.io/api/forms/AbstractControl#updatevalueandvalidity

How to have no validation when selecting a value on dropdown

On this form to create a link when I select another committee type the form validates for all of the blank fields that are required. I am trying to figure out a way so those fields don't validate when I select another committee type in the dropdown. Currently when I debug it doesn't get to the post action method in the controller for obvious reasons that the form validates before even getting into the controller.
If you need to see more code like the action method in controller or view model I can provide that as well.
View
<div class="form-group col-md-8">
<div asp-validation-summary="All" id="validation-error" class="text-danger custom-validation-
summary"></div>
</div>
<input id="link-id" asp-for="#Model.LinkId" type="hidden" />
<input name="FetchCategories" type="hidden"/>
<div class="form-group col-md-8 col-lg-4">
<div class="form-group">
#{
var authorizedCommitteeTypes = await Model.CommitteeType
.ToSelectListAsync(AuthorizationService, User, AuthRequirements.AdminCommitteeType);
if (authorizedCommitteeTypes.Count == 1)
{
<input id="committeeType" name="committeeType" type="hidden"
value="#authorizedCommitteeTypes.FirstOrDefault()?.Value" />
}
else
{
<label class="control-label">Committee Type</label>
<select id="add-edit-committee-type"
name="committeeType"
asp-for="#Model.CommitteeType"
asp-items="#authorizedCommitteeTypes"
class="form-control">
</select>
}
}
</div>
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Category</label>
#{
if (Model != null && Model.AvailableCategories != null)
{
var availableCategories =
new SelectList(
Model.AvailableCategories.OrderBy(c => c.Order),
dataValueField: "CategoryId",
dataTextField: "Title",
selectedValue: Model.CategoryId);
<select id="dropdown-linkCategories" required
asp-for="#Model.CategoryId"
asp-items="#availableCategories"
class="form-control">
<option>-- Select --</option>
</select>
}
else
{
<select id="dropdown-linkCategories"
class="form-control">
<option>-- Select --</option>
</select>
}
}
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Title</label>
<input id="title" asp-for="Title" name="Title" class="form-control" />
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">Display Order</label>
<div>
<input id="order" asp-for="Order" name="Order" class="form-control" />
</div>
</div>
<div class="form-group col-md-8 col-lg-4">
<label class="control-label">URL</label>
<input id="url" asp-for="URL" name="URL" class="form-control" />
</div>
<div class="form-group col-md-8 col-lg-12">
<label class="control-label">Description</label>
<textarea class="rtextDescription" name="Description" id="Description" row="1" cols="60"
data-val-maxlength-max="200" asp-for="Description"
data-val-maxlength="Max length for Description is 200"></textarea>
</div>
#{
if (Model.LinkId == 0)
{
<div class="form-group col-md-12">
<input type="submit" id="link-submit"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2"
value="Add" />
<a asp-area="Admin"
asp-controller="Link"
asp-action="Index"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2">Back to Links</a>
</div>
}
else
{
<div class="form-group col-md-8 col-lg-12">
<input type="submit" value="Save" id="edit-submit"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2" />
<a asp-area="Admin"
asp-controller="Link"
asp-action="Index"
class="btn btn-forum col-sm-12 col-md-2 col-lg-2">Back to Links</a>
</div>
}
}
JS
$(document).on("change", "#form-create-link #add-edit-committee-type", function () {
$('input[name="FetchCategories"]').val(true);
$(this).closest('form').submit()
});

Angular 8 ReactiveForm Input type "file" doesn't recognize value on Edge

I am using private _fb: FormBuilder to build my form in Angular 8. My form is initialized like this
this.itemForm = this._fb.group({
title: ['', [Validators.required, this._systemSvc.nonSpaceString]],
file: ['', Validators.required],
categories: [''],
tags: ['']
});
The template is
<form class="needs-validation" [formGroup]="itemForm" (ngSubmit)="createPost()">
<div class="form-row">
<div class="col-md-4 mb-3">
<div class="form-row mb-3">
<div class="col-md-12 mb-3">
<label class="text-primary"><strong>Title</strong></label>
<input type="text" formControlName="title" class="form-control"
[ngClass]="{ 'is-invalid': checkError('title') }">
<div *ngIf="checkError('title')" class="invalid-feedback">
<div *ngIf="f.title.errors.required">Title is required</div>
<div *ngIf="f.title.errors.whitespace">Title can't be blank space</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6 mb-3">
<label class="text-primary"><strong>Categories</strong></label>
<select formControlName="categories" class="custom-select">
<option value="">--Select categories--</option>
<option value="Funny">Funny</option>
<option value="Music">Music</option>
<option value="Adventure">Adventure</option>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-md-12 mb-3">
<label class="text-primary" for="tags"><strong>Tags</strong></label>
<div>
<ng-container *ngFor="let tag of parsedTags;">
#{{tag}}
</ng-container>
</div>
<input id="tags" type="text" formControlName="tags" class="w-100"
(input)="onTagsChange($event.target.value)">
</div>
</div>
</div>
<div class="col-md-7 mb-3 offset-md-1">
<div class="form-row mb-3">
<div class="col-md-12 mb-3">
<label class="text-primary" for="upload"><strong>Choose file</strong></label>
<div class="custom-file">
<label class="custom-file-label" for="upload">Choose file</label>
<input type="file" class="custom-file-input" formControlName="file" id="upload"
(change)="handleFileInput($event.target.files)" accept="audio/*, video/*, image/*"
[ngClass]="{ 'is-invalid': checkError('file') }">
<div *ngIf="checkError('file')" class="invalid-feedback">
<div *ngIf="f.file.errors.required">File is required</div>
</div>
</div>
</div>
</div>
<div class="form-row mb-3">
<div class="col-md-12 mb-3">
<img *ngIf="uploadedFile" src="{{uploadedFile}}" class="w-100" id="previewImg">
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-2 form-group">
<button type="button" id="cancelBtn" class="btn btn-primary mr-2" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success">Post</button>
</div>
</div>
</form>
Every thing work well on Firefox and Chrome. But when it come to Edge, user select file but the reactive form doesn't recognize the selected file. Other controls like input = text and drop down are still ok on Edge. The form is invalid and say only the file is empty. This is the snapshot of the form
controls: Object
dirty: true
disabled: false
enabled: true
errors: null
invalid: true
parent: undefined
pending: false
pristine: false
root: Object
status: "INVALID"
statusChanges: Object
touched: true
untouched: false
updateOn: "change"
valid: false
validator: null
value: Object
categories: "Funny"
file: ""
tags: "asd"
title: "asd"
I had the same problem and I have resolved that by manualy set validation to null.
Create function in which check if input has file or not and inside it use below:
this.itemForm.controls['file'].setErrors(null)
It really works.

jQuery Cloning and incrementing input, textarea, that has name, id and for

I'm still very new to jQuery, and would need help to how to increment 3 elements in this code.
name, id & for.
The name consist of products[0]category, id consist of checkbox[0], for consist of checkbox[0] which is for labels on the checkbox that id use.
I've tried searching for examples. But all them haven't found any good results that i could learn from unfortunately. So in the codes below, they're not there to increase increment as i have totally no idea what else i can do to increase increment numbering.
$(document).ready(function() {
let $append = $('#append');
// append location's data listing
$append.on('change', '.location', function(){
var value = $(this).val();
$('.location_id').val($('#locations [value="'+value+'"]').data('locationid'));
$('.loc_desc').val($('#locations [value="'+value+'"]').data('locdesc'));
});
// enable checkbox for serialnumbers
$append.on('change','.enable-serial', function(){
let $item = $(this).closest('.product-item');
let $checkbox = $item.find('.enable');
$checkbox.prop('disabled', !this.checked);
});
// ctrl for key in checkbox
$append.on('click', '.keyin-ctrl', function() {
let $container = $(this).closest('.product-item');
let $serial = $container.find('.serial');
$container.find('.display').val(function(i, v) {
return v + $serial.val() + ';\n';
});
$serial.val('').focus();
});
// ctrl for del textarea
$append.on('click', '.undo-ctrl', function() {
let $container = $(this).closest('.product-item');
$container.find('.display').val('');
});
// clone product, increment products[x]var
$('#add_product').on('click', function() {
var itemNo = $('.product-item').length + 1;
var index = $('.product-item').length;
var regex = /^(.+?)(\d+)$/i;
let $product = $append.find('.product-item.template')
.clone()
.show()
.removeClass('template')
.insertAfter('.product-item:last');;
$product.find('span').text('#' + itemNo);
$product.find(':checkbox').prop('checked', false);
$product.find('.enable').prop('disabled', true);
$product.find('input, textarea').val('');
$('#append').append($product);
});
// delete product, but remain original template intact
$('#delete_product').on('click', function(){
var itemNo = $('.product-item').length + 1;
let $product = $append.find('.product-item:last:not(".template")');
$product.remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main class="shadow border">
<h4>{{ __('Product Details') }}</h4>
<hr>
<form method="post" action="">
<!-- Multiple Product addition -->
<div class="form-group row">
<label class="col-sm-2 col-form-label font-weight-bold">{{ __('Product Setting') }}</label><br/>
<div class="col-sm-5">
<button type="button" id="add_product" class="btn btn-dark">{{ __('Add Product') }} <i class="fas fa-plus-square"></i></button>
<button type="button" id="delete_product" class="btn btn-dark ml-3">{{ __('Delete Last Product') }} <i class="fas fa-minus-square"></i></button>
</div>
</div>
<hr>
<!-- Frist Group -->
<div class="product" id="append">
<!-- Product Details -->
<div class="product-item template">
<span>#1</span>
<div class="form-group row">
<label class="col-sm-2 col-form-label font-weight-bold">{{ __('Category') }}</label>
<div class="col-sm-2">
<input class="form-control" name="products[0]category" type="text" placeholder="eg. 333" maxlength="3"required>
</div>
<label class="col-sm-1 col-form-label font-weight-bold">{{ __('Code') }}</label>
<div class="col-sm-2">
<input class="form-control" name="products[0]code" type="text" placeholder="eg. 22" maxlength="2" required>
</div>
<label class="col-sm-1 col-form-label font-weight-bold">{{ __('Partnumber') }}</label>
<div class="col-sm-2">
<input class="form-control" name="products[0]partnumber" type="text" placeholder="eg. NGH92838" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label font-weight-bold">{{ __('Brand') }}</label>
<div class="col-sm-2">
<input class="form-control" name="products[0]brand" type="text" placeholder="eg. Rototype" required>
</div>
<label class="col-sm-1 col-form-label font-weight-bold">{{ __('Quantities') }}</label>
<div class="col-sm-2">
<input class="form-control" name="products[0]qty" type="number" placeholder="eg. 1" required>
</div>
<label class="col-sm-1 col-form-label font-weight-bold">{{ __("Location") }}</label>
<div class="col-sm-2">
<input class="form-control location" type="text" name="products[0]loc_name" list="locations" value="">
<input type="hidden" class="location_id" name="products[0]location_id" value="">
<input type="hidden" class="loc_desc" name="products[0]loc_desc" value="">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label font-weight-bold">{{ __("Description") }}</label>
<div class="col-sm-8">
<input class="form-control" name="products[0]description" type="text" placeholder="eg. Spare part for CSD2002">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label font-weight-bold">{{ __('Seial Number(s)') }}</label>
<div class="col-sm-5">
<input class="form-control enable serial" maxlength="25" placeholder="Key in Serial Number and hit button 'Key In'" disabled>
</div>
<div class="col-sm-5">
<button class="btn btn-dark enable keyin-ctrl" type="button" disabled>{{ __('Key In') }}</button>
<button class="btn btn-dark enable undo-ctrl" type="button" disabled>{{ __('Del') }}</button>
<input class="form-check-input ml-4 mt-2 pointer enable-serial" id="checkbox[0]" type="checkbox">
<label class="form-check-label ml-5 pointer" for="checkbox[0]">{{ __('tick to enable serialnumber')}}</label>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label"></label>
<div class="col-sm-5">
<textarea class="form-control display" name="products[0]serialnumbers" rows="5" style="resize: none;" placeholder="eg. SGH8484848" readonly></textarea>
</div>
</div>
<hr>
</div>
<!-- append start -->
</div>
<div class="form-group row">
<div class="col-sm-12 ">
#csrf
<button type="submit" class="btn btn-dark float-right ml-4">Next <i class="fas fa-caret-right"></i></button>
<!--<button type="button" class="btn btn-secondary float-right" onclick="history.back()">Previous</button>-->
</div>
</div>
<datalist id="locations">
#foreach($locations as $location)
<option value="{{ $location->loc_name}}" data-locationid="{{ $location->location_id }}" data-locdesc="{{ $location->loc_desc }}"></option>
#endforeach
</datalist>
</form>
</div>
</main>
So how do I actually achieve this to add increment to the NAME, ID and FOR my clones?
From the original template of products[0]variable to products[1]variable, checkbox[0] to checkbox[1]
If you want to increment either an ID, class, etc. you can't use .clone(), like the documentation warns:
Using .clone() has the side-effect of producing elements with
duplicate id attributes, which are supposed to be unique. Where
possible, it is recommended to avoid cloning elements with this
attribute or using class attributes as identifiers instead.
You'll have to do it "manually", following a very simple example below:
$( "#addrow" ).click(function() {
var count = $("#product").children().length;
$("#product").append("<input id='field[" + count + "]' type='text'>");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="product">
</div>
<input id="addrow" type="button" value="Add field">

Angular 6 dynamic rows resets while adding

add purchase html
<div class="d-flex justify-content-center align-items-center">
<div class="col-md-12 border">
<div class="card-header header-elements-inline">
<h4 class="card-title">Add Purchase</h4>
<button [mat-dialog-close]="true" type="button" class="bootbox-close-button close" data-dismiss="modal"
aria-hidden="true">×</button>
</div>
<form action="" #addPurchaseForm="ngForm" class="purchaseForm" (ngSubmit)="addPurchase(addPurchaseForm)" method="POST">
<div class="card-body">
<div class="col-md-12">
<div class="row justify-content-center">
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Select vendor to add product</label>
<ng-select [items]="vendorData" bindLabel="vendor_name" bindValue="vendor_id" name="vendor_name" #vendor_name="ngModel"
[searchable]="false" required appendTo="body" [closeOnSelect]="true" [(ngModel)]="purchaseDetails.vendor_id">
</ng-select>
<span *ngIf="addPurchaseForm.submitted && vendor_name.errors?.required" class="form-text text-danger">Product Sub
Vendor
is
Required</span>
</div>
</div>
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Reciept No</label>
<input [(ngModel)]="purchaseDetails.reciept_no" name="reciept_no" #reciept_no="ngModel" type="text" required class="form-control">
<span *ngIf="addPurchaseForm.submitted && reciept_no.errors?.required" class="form-text text-danger">Product code
is
Required</span>
</div>
</div>
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Purchased At</label>
<mat-form-field>
<input [(ngModel)]="purchaseDetails.purchased_at" name="purchased_at" #purchased_at="ngModel" required class="form-control" matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<!-- <input [(ngModel)]="purchaseDetails.purchased_at" name="purchased_at" #purchased_at="ngModel" type="text" required class="form-control"> -->
<span *ngIf="addPurchaseForm.submitted && purchased_at.errors?.required" class="form-text text-danger">Product code
is
Required</span>
</div>
</div>
</div>
<h4 class="card-title">Purchase Details</h4>
<mat-dialog-content style="max-height:200px">
<div class="row" *ngFor="let purchaseDetail of purchaseDetails; let i = index;">
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Select Product</label>
<ng-select [items]="productData" bindLabel="product_name" bindValue="product_id" name="vendor_name" #product[i]="ngModel"
[searchable]="false" required appendTo="body" [closeOnSelect]="true" [(ngModel)]="purchaseDetails[i].product_id">
</ng-select>
<span *ngIf="addPurchaseForm.submitted && vendor_name.errors?.required" class="form-text text-danger">Product Sub
Vendor
is
Required</span>
</div>
</div>
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Unit Rate</label>
<input mask="0*.0*" value="{{purchaseDetails[i].rate}}" [(ngModel)]="purchaseDetails[i].rate" name="product_rate" #rate[i]="ngModel" type="text" required class="form-control">
<span *ngIf="addPurchaseForm.submitted && code.errors?.required" class="form-text text-danger">Rate
is
Required</span>
</div>
</div>
<div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Quantity</label>
<input mask="0*" value="{{purchaseDetails[i].quantity}}" [(ngModel)]="purchaseDetails[i].quantity" name="product_quantity" #quantity[i]="ngModel" type="text" required class="form-control">
<span *ngIf="addPurchaseForm.submitted && code.errors?.required" class="form-text text-danger">Quantity
is
Required</span>
</div>
</div>
<!-- <div class="col-md">
<div class="form-group form-group-float">
<label class="form-group-float-label is-visible">Price</label>
<input disabled [(ngModel)]="purchaseDetails[i].quantity * purchaseDetails[i].rate" name="product_price" #price="ngModel" type="text" required
class="form-control">
<span *ngIf="addPurchaseForm.submitted && code.errors?.required" class="form-text text-danger">Price
is
Required</span>
</div>
</div> -->
<div class="col-md-1 align-self-md-center">
<i (click)="removePurchaseDetail(i)" class="icon-minus-circle2 cursor-pointer fs-22 text-danger"></i>
</div>
</div>
</mat-dialog-content>
<div class="row justify-content-center mb-25">
<i (click)="addNewPurchaseDetail()" class="icon-plus-circle2 fs-22 cursor-pointer text-indigo-800"></i>
</div>
</div>
<div class="text-center">
<button type="submit" [disabled]="!purchaseDetails.vendor_id" class="btn btn-primary">Add purchase <i class="icon-paperplane ml-2"></i></button>
</div>
</div>
</form>
</div>
</div>
Add purchase component
import { Component, OnInit, Inject } from '#angular/core';
import { MAT_DIALOG_DATA } from '#angular/material';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-add-purchase',
templateUrl: './add-purchase.component.html',
styleUrls: ['./add-purchase.component.css']
})
export class AddPurchaseComponent implements OnInit {
purchaseDetails : any = [{
product_id : '',
rate : '',
price : '',
quantity : ''
}];
vendorData : any;
productData : any;
constructor(#Inject(MAT_DIALOG_DATA) private addPurchaseData : any) { }
ngOnInit() {
console.log(this.addPurchaseData);
console.log(this.purchaseDetails);
this.vendorData = this.addPurchaseData.vendors;
this.productData = this.addPurchaseData.products;
}
addNewPurchaseDetail(){
console.log(this.purchaseDetails);
this.purchaseDetails.push({
product_id: '',
rate: '',
price: '',
quantity: ''
});
}
removePurchaseDetail(index){
this.purchaseDetails.splice(index, 1);
}
}
while adding new purchase details row
i'am able to get the row but my values are resetting
i don't know what i am doing wrong
Is there any right way to achieve this
I am new to angular pls guide me through this
when i console logged the model values it was there but i don't know why the rows has been resetted
Found the issue:
Input name should be like this:
<input name="reciept_no[{{i}}]" [(ngModel)]="purchaseDetails.reciept_no" #reciept_no="ngModel" type="text" required class="form-control">
I had like this :
<input name="reciept_no" [(ngModel)]="purchaseDetails.reciept_no" #reciept_no="ngModel" type="text" required class="form-control">

Categories