I'm using Angular 6 and the module ngx-chips to use ng-input field, so this is the HTML template:
<div class="form-group container">
<div class="row">
<div class=" col-sm-12">
<label for="FormControlAlias"
class="col-sm-2 col-form-label float-left">Alias</label>
<div class="col-sm-8 float-left" >
<tag-input #alias [(ngModel)]="aliasList"
[secondaryPlaceholder]="'Enter the project aliases'"
[placeholder]="'Enter an alias'"
[modelAsStrings]="true"
name="alias" [separatorKeyCodes]="[188]" > </tag-input>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary"
(click)="addAlias(alias.value);>Add</button>
Here is the function I call by clicking the button:
addAlias( alias: Array<string>): void {
console.log(alias.value);
}
in the console I get this error :
ERROR TypeError: "alias is undefined"
I want to get the value of #alias and make a post request into the database, but I can't retrieve the value.
You have to define aliasList as a variable in your class.
After you can retreive the value with :
addAlias(): void{
console.log(this.aliasList);
}
You need not send alias value from template. You already have those values in aliasList set via ngModel. Just use that.
addAlias() {
console.log(this.aliasList);
}
template
<button type="button" class="btn btn-primary"
(click)="addAlias()">Add</button>
Related
Fairly new to stack overflow but I needed assistance.
I did a backend and the API is working fine after tests from postman.
I can add employee and I can retrieve employee. However, what I am trying to do is, when I click on the card, I want the card I clicked on to display information about the employee in the textboxes and allow me to change and update. I am failing to retrieve and update my HTML. Please help.
In MY TS, I have this:
updateEmployee(employee: Employee){this.load = true;this.users.updateEmployee(employee).subscribe(res => {this.load = false;this.onPrimaryOutline("Employee has been updated");this.getEmployee();},err=>{console.log(err);this.load = false;this.onErrorOutline("Failed to update Employee, please try again");});}
onOpenModal(employee: Employee, mode: string): void {const containerUpdate = document.getElementById('update-container');const button = document.createElement('button');button.type = 'button';button.style.display = 'none';button.setAttribute('data-toggle', 'modal');if (mode === 'save'){this.updateEmployee = employee;button.setAttribute('data-target', '#update-container');}if (mode === 'delete'){button.setAttribute('data-target', '#deleteEmployeeMasterModal');} containerUpdate.appendChild(button);
button.click()}
service:
public updateEmployee(employee: Employee): Observable<Employee>{ return this.http.put<Employee>(${this.updateEmployee_url}/employee/update, employee) }
HTML:
<div class="card" id="update-container" [hidden]="!showForm" data-toggle="modal" data-target="#updateEmployeeModal"><span aria-hidden="true">×</span><ng-template #template><ngx-loading-x [show]="load"></ngx-loading-x><div NgxLoadingXBlur [show]="load"><div class="modal-header">
<div>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span> </button>
</div>
<div class="modal-body">
<div class="card mb-4">
<div class="card-body">
<h6 class="mb-4">{{ 'forms.external-components' | translate }}
</h6>
<form [formGroup]="commonForm" #editForm="ngForm" (ngSubmit)="updateEmployee()" novalidate class="tooltip-label-right">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" ngModel="{{editEmployee?.name}}" formControlName="name">
<small>Only letters and at least 2 characters</small>
<div *ngIf="commonForm.get('name')?.errors?.required && !form.submitted" class="invalid-tooltip">Name is required!</div>
</div>
<div class="form-group">
<label>Surname</label>
<input type="text" class="form-control" name="airlineCode" ngModel="{{editEmployee?.surname}}" formControlName="surname">
<small>Only letters and at least 2 characters</small>
<div *ngIf="commonForm.get('surname')?.errors?.required && !form.submitted" class="invalid-tooltip">Code is required!</div>
</div>
<div class="form-group">
<label>Number</label>
<input type="text" class="form-control" name="phonenumber" ngModel="{{editEmployee?.phonenumber}}" formControlName="phonenumber">
<div *ngIf="commonForm.get('phonenumber')?.errors?.required && !form.submitted" class="invalid-tooltip">Number is required!</div>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!commonForm.valid" (click)="updateEmployee(employee, Employee)" (click)="modalRef.hide()">Update</button>
<button type="button" class="btn btn-danger" style="display: inline-block;margin-left: 20px;" (click)="delete()" (click)="modalRef.hide()">Delete</button>
</form>
</div>
</div>
</div>
</div>
I just need to retrieve the values for the specific card when I click on it and be able to update it. But I cannot see what I am omitting. Inspect element says:
ngModel cannot be used to register form controls with a parent formGroup directive. Try using
formGroup's partner directive "formControlName" instead
What I am trying to do:
I am building a form repeater, Now I have the plugin working and able to add fields etc, The main form is for setting up a survey with the following logic:
OUTER REPEATER:
Question: input type text \ **Question Type: **input type select
INNER REPEATER:
Choice (can add multiple choices)
On Question Type users can choose a question type and have the option to choose a Single / multiple choice input: at this point I want the nested inner field to be visible (Choice)
So if the choice type is a rating, or a text answer, do not show the nested Choices repeater field only show it when the choice is a single or multiple choice answer.
CODE:
HTML
<!--begin::Repeater-->
<div id="survey">
<div class = "card card-flush shadow-sm">
<div class = "card-header">
<h3 class = "card-title">Survey Questions</h3>
</div>
<div class = "card-body py-2">
<!--begin::Form group-->
<div class="form-group">
<div data-repeater-list="survey">
<div data-repeater-item>
<div class="form-group row">
<div class="col-md-5">
<label class="form-label">Question:</label>
<input type="text" class="form-control form-control-solid mb-5" placeholder="Enter question..." name = "survey[questions][name]"/>
</div>
<div class="col-md-5">
<label class="form-label">Answer Type:</label>
<select class = 'form-select form-select-solid' placeholder = "Choose a question type..." id = "questionType" name = "survey[questions][type]">
<option disabled selected>Choose a question type</option>
<option value = "STANDARD">Open-Ended</option>
<option value = "BOOLEAN">Yes/No Question</option>
<option value = "RATING">Rating</option>
<option value = "SLIDER">Slider</option>
<option value = "SINGLE" id = "additionalSurveyOptions">Single Choice</option>
<option value = "MULTIPLE" id = "additionalSurveyOptions">Multiple Choice</option>
<option value = "NUMBER">Number Input</option>
</select>
</div>
<div class="col-md-2">
<a href="javascript:;" data-repeater-delete class="btn btn-light-danger mt-3 mt-md-8 w-100">
<i class="la la-trash-o"></i>Delete
</a>
</div>
</div>
<div class="inner-repeater mb-5">
<div class = "row">
<div class = "col-7 offset-5">
<div data-repeater-list="choices">
<div data-repeater-item>
<label class="form-label">Choice:</label>
<div class="input-group pb-1">
<input type="text" class="form-control form-control-solid" placeholder="Enter choice here..." name = "choice"/>
<button class="border border-secondary btn btn-icon btn-light-danger" data-repeater-delete type="button">
<i class="la la-trash-o fs-3"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<div class = "row">
<div class = "col-7 offset-5">
<button class="btn btn-light-primary mt-3 mt-md-8 w-100" data-repeater-create type="button">
<i class="la la-plus"></i> Add a Choice
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!--end::Form group-->
</div>
<div class = "card-footer">
<a href="javascript:;" data-repeater-create class="btn btn-light-primary w-100">
<i class="la la-plus"></i>Add a Question
</a>
</div>
</div>
</div>
<!--end::Repeater-->
JAVASCRIPT
<!-- Tools :: Repeater (Begin) -->
<script>
$('#survey').repeater({
repeaters: [{
selector: '.inner-repeater',
show: function () {
$(this).slideDown();
},
hide: function (deleteElement) {
$(this).slideUp(deleteElement);
}
}],
show: function () {
$(this).slideDown();
},
hide: function (deleteElement) {
$(this).slideUp(deleteElement);
}
});
</script>
<!-- Tools :: Repeater (End) -->
I'm not 100% sure where to start
So I guess to summarise:
How do I hide / show the inner repeater based on the selected option in the outer-repeater
Thanks
I have tried wrapping the repeaters in an if statement (if this.value === "SINGLE") ...
repeaters: [{
selector: '.inner-repeater',
show: function () {
$(this).slideDown();
},
hide: function (deleteElement) {
$(this).slideUp(deleteElement);
}
}],
No luck
I tried setting the display visibility to hidden on the main div itself, then when the input value is SINGLE / MULTIPLE display the inner block... this worked (but it showed the option for every repeated form input) - I just want it to show on the element with the option selected
I have a form with couple of dropdowns which looks like this:
<form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
<button type="button" class="btn btn-outline-primary w-100 dropdown-toggle" id="operatorDropdown"
ngbDropdownToggle>{{operator.name ? operator.name : 'Select your operator' | translate}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownExample" class="w-100 mb-3" #dropdownmenu >
<button type="button" *ngFor="let option of operators" class="dropdown-item" (click)="operator = option"
[ngClass]="{'active':operator.name === option.name}">{{option.name}}</button>
</div>
</form>
I'm having a tough time adding a simple validation to this dropdown. I want to display an error if no option is selected after pressing Submit button. Tried various validation examples on angular but none of them seems working with this kind of dropdown(without <input> etc.)
Also tried something like this, but I believe it is far from working properly.
<div *ngIf="f.controls.operatorDropdown?.errors">Error message goes here. </div>
I've managed to create the solution myself. I made that before submitting, my component would check if the operator.name is undefined(not selected). If it was, it would unhide the error message, if not it would just proceed and submit the form.
Also added the validation to (click) button event, so after the error is shown if the user chooses the operator it would validate that the operator.name is not undefined anymore and would hide the error message.
I'll share my final version, feel free to comment.
component.html
<form name="form" #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
<div ngbDropdown [className]="!isOperatorEmpty ? 'u-mw-300p u-mw-xs-100' : 'u-mw-300p u-mw-xs-100 is-invalid'">
<button type="button" class="btn btn-outline-primary w-100 dropdown-toggle" id="operatorDropdown"
ngbDropdownToggle>{{operator.name ? operator.name : 'Select your operator' | translate}}</button>
<div ngbDropdownMenu aria-labelledby="dropdownExample" class="w-100 mb-3">
<button type="button" *ngFor="let option of operators" class="dropdown-item" (click)="operator = option;validateOperatorDropdown()"
[ngClass]="{'active':operator.name === option.name}">{{option.name}}</button>
</div>
</div>
<div class="invalid-feedback u-mw-300p u-mw-xs-100" [hidden]="!isOperatorEmpty">{{"Please select operator." | translate}}</div>
</form>
component.ts
validateOperatorDropdown() {
if (this.operator.name === undefined) {
this.isOperatorEmpty = true;
} else {
this.isOperatorEmpty = false;
}
}
onSubmit(f: FormsModule) {
this.validateOperatorDropdown()
if (!this.isOperatorEmpty) {
//continue
}
}
I have created a form using reactive form approach. I'm creating a formGroup with 2 formControls on each button click.
On Submitting the form, I'm trying to get the values of the FormGroup which is a FormArray, but the value is not retrieved.
HTML code where I loop through the controls and create the needed formControls
<div class="row" formArrayName="ingredients">
<div class="col-md-12" >
<div class="row"
*ngFor="let ingredientControl of
recipeForm.get('ingredients').controls;
let index = index"
[formGroupName]="index"
style="margin-top: 10px;"
>
<div class="col-sm-8">
<input type="text"
class="form-control"
formControlName="ingredientName"
>
</div>
<div class="col-sm-3">
<input type="number"
class="form-control"
formControlName="ingredientAmount"
>
</div>
<div class="col-xs-2">
<button class="btn btn-danger" type="button"
(click)="onDeleteIngredient(index)"> X
</button>
</div>
</div>
</div>
</div>
.ts file where I try to get the FormControl values
I submit the form in the template using (ngSubmit)="onSubmit()"
onSubmit(){
const newRecipe = new RecipeModel(
this.recipeForm.value['recipeName'],
this.recipeForm.value['imagePath'],
this.recipeForm.value['description'],
this.recipeForm.value['ingredients'],
);
this.recipeService.addNewRecipe(newRecipe);
}
Here, this.recipeForm.value['ingredients'] is returning empty. But while trying to print the FormArray value, the control has value.
I expect the form to return the ingredientName and ingredientAmount so that I can pass the value to the service method. But I'm not getting the value form the form.
I am validating my template using angular2, but meanwhile it shows this error:
Cannot read the property 'errors' of undefined.
Here is my template:
<h3 class = "head">{{title}}</h3>
<form [ngFormModel]="form" #f="ngForm">
<div class="row">
<div class="form-group">
<label class="formHeading">Facebook</label>
<input type="text" id="facebook" class="form-control col-xs-3" ngControl="facebook" #facebook="ngForm" >
</div>
<div *ngIf ="facebook.touched && facebok.errors">
<div class="form-row btn">
<button type="submit" class="btn btn-primary pull-right butspace" [disabled]="!f.valid">Save</button>
</div>
</div>
</form>
I dont know why it shows this error. Can anyone fix it?
First of all, you have facebok instead of facebook on the error property.
If that doesn't fix it you're probably using the facebook object before it is assigned, which can happen if it's an #Input() for example.
Use the Elvis operator:
*ngIf ="facebook?.touched && facebook?.errors"