How to select button in angular
Here is my code from template.
ngOnInit() {
}
<div class="form-group">
<ng-container *ngFor="let lib of library; let i=index">
<div class="radio">
<input type="radio" id="library-{{i}}" name="lib-books"
(change)="selectOnChange($event)"
[value]="lib">
<label for="library-{{i}}"></label>
</div>
<label for="library-{{i}}">{{lib}}</label>
</ng-container>
</div>
Create a property isSelected to your lib object and
Sets up two-way data binding to your radio button:
[(value)]="lib.isSelected"
Equivalent to:
(valueChange)="lib.isSelected=$event"
You should use a Form component, either template driven or reactive
Template driven: You use two-way-binding for ngModel to store the selected value in your form model:
export class AppComponent {
library:string[] = [
'lib1', 'lib2', 'lib3'
];
// note: you should create an interface for that
model = {
books: '',
}
onSubmit () {
// save the selection
}
}
The difference to your code: the two-way binding to the model field [(ngModel)]="model.books"
<div class="form-group" onsubmit="onSubmit()">
<ng-container *ngFor="let lib of library; let i=index">
<div class="radio">
<input type="radio" id="library-{{i}}" name="lib-books"
[(ngModel)]="model.books"
[value]="lib">
<label for="library-{{i}}"></label>
</div>
<label for="library-{{i}}">{{lib}}</label>
</ng-container>
</div>
And don't forget to import the forms module in app.module.ts
import { FormsModule } from '#angular/forms';
#NgModule({
imports: [ FormsModule ],
})
Check out the StackBlitz for the template driven solution
Reactive forms (my personal preference, especially with the form builder):
export class AppComponent {
library: string[] = [
'lib1', 'lib2', 'lib3'
];
myForm: FormGroup;
constructor(private __fb: FormBuilder) {
this.createForm();
}
createForm() {
this.myForm = this.__fb.group({
book: ''
});
}
onSubmit() {
// save the selection
}
}
Note: the name attribute of the <input> needs to be the same as the formControlName and the <form> tag needs a [formGroup] binding.
<form [formGroup]="myForm" onsubmit="onSubmit()">
<div class="form-group">
<ng-container *ngFor="let lib of library; let i=index">
<div class="radio">
<input type="radio"
[value]="lib"
name="book"
formControlName="book"
id="library-{{i}}"
>
</div>
<label for="library-{{i}}">{{lib}}</label>
</ng-container>
</div>
</form>
Check out the StackBlitz for the reactive solution
Related
This is my code so far:
My component.html:
<div class="container">
<Form #a ="ngForm" ngForm (ngSubmit)="onSubmit(a)">
<div *ngFor="let question of questions">
<div class = "form-group">
<a>{{question.questionId}}. {{question.question}}</a><br>
<input type="radio" ngModel name="Ans{{question.questionId}}" value="A" >
<label for="html">A. {{question.optionsA}}</label><br>
<input type="radio" ngModel name="Ans{{question.questionId}}" value="B" >
<label for="html">B. {{question.optionsB}}</label><br>
<input type="radio" ngModel name="Ans{{question.questionId}}" value="C" >
<label for="html">C. {{question.optionsC}}</label><br>
<input type="radio" ngModel name="Ans{{question.questionId}}" value="D" >
<label for="html">D. {{question.optionsD}}</label><br>
</div>
</div>
<button class="btn btn-primary " type="submit" >Submit</button>
</Form>
<div *ngIf="results.length >0">
<table>
<thead>
<th>Question No.</th>
<th>Correct Answer</th>
<th>Your Answer</th>
</thead>
<tbody *ngFor="let question of questions">
<td>{{question.questionId}}</td>
<td>{{question.answer}}</td>
</tbody>
</table>
{{score}}
{{results.length}}
</div>
</div>
and my component.ts:
import { Component, OnInit } from '#angular/core';
import { Quiz1 } from 'src/app/models/quiz1.model';
import { Quiz1Service } from 'src/app/services/quiz1.service';
import {FormControl, FormGroup, NgForm} from '#angular/forms';
#Component({
selector: 'app-quiz1',
templateUrl: './quiz1.component.html',
styleUrls: ['./quiz1.component.css']
})
export class Quiz1Component implements OnInit {
questions?: Quiz1[];
currentQuestion: Quiz1 = {};
currentIndex = -1;
score = 0;
results:String[] = [];
//index?: String[] = ['Ans1','Ans2'];
constructor(private quiz1Service: Quiz1Service) { }
ngOnInit(): void {
this.retrieveQuestions();
}
retrieveQuestions(): void {
this.quiz1Service.getAll()
.subscribe({
next: (data: any) => {
this.questions = data;
console.log(data);
},
error: (e: any) => console.error(e)
});
}
onSubmit(a:NgForm){
this.results?.push(a.value);
console.log(this.results);
console.log(this.results.length)
this.questions?.forEach((questions) => {
console.log(questions.questionId);
if(questions.answer==this.results[questions.questionId-1]){
this.score++
console.log(this.score)
}
});
}
}
When I print the results array in the console, this is what I got:
Array(1)
0: {Ans1: 'A', Ans2: 'C'}
length: 1
[[Prototype]]: Array(0)
as you can see, it is storing all the data in a single index and with the field name which won't do at all.
What I want is just the field data stored in different index in the array so I can use that.
Is that possible?
I don't think you can achieve what you want using template-driven forms.
You would have to use reactive forms and FormArray.
I'm working on angular 5 Reactive Forms :
I had this error :
There is no directive with "exportAs" set to "ngModel"
I saw in others forums that problem can be for many reasons :
misspelling in the HTML template , forgetting to import "FormsModule" or "ReactiveFormsModule", ....
I checked my code but i didn't find the issue
Can you Help me please !!!
Console error :
There is no directive with "exportAs" set to "ngModel" ("
[(ngModel)]="user.FirstName"
formControlName="FirstName"
[ERROR ->]#FirstName="ngModel" />
<label for="firstName">{{ 'FIRST_NAME' | translate:param}}</label>")
: ng:///AppModule/LoginComponent.html#12:15
app.module.ts:
//angular moudel
import { NgModule } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
....
#NgModule({
declarations: [
.....
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
...
AppRoutingMoudel,
],
...
})
LoginComponent.ts
import { Component, OnInit } from '#angular/core';
import { User } from './../../../model/user';
import {FormBuilder,FormGroup,FormControl,Validators,NgForm} from '#angular/forms'
....
export class LoginComponent implements OnInit {
user : User;
userLoginForm: FormGroup;
constructor(private userLoginFormBuilder:FormBuilder) {
this.user = new User ("TestName", "Yagmi",
"TestName#Yagmi.com", "esay", "esay");
this.userLoginForm = this.userLoginFormBuilder.group({
FirstName: new FormControl (this.user.FirstName,
[Validators.minLength(4),])
});
}
}
LoginComponent.Html
<form class="col s12" [formGroup]="userLoginForm" (ngSubmit)="saveUserLogin()">
<div class="row">
<div class="input-field col s12 m6">
<input id="firstName"
type="text"
class="validate"
[(ngModel)]="user.FirstName"
formControlName="FirstName"
#FirstName="ngModel" />
<label for="firstName">{{ 'FIRST_NAME' | translate:param }}</label>
<p class="data-error data-validation" *ngIf="FirstName.errors?.minlength">
min length is 4 caracters.
</p>
<p class="data-error data-validation" *ngIf="FirstName?.touched">
touched.
</p>
</div>
</div>
</form>
user.ts
export class User {
constructor(
public FirstName: string,
public LastName: string,
public Email: string,
public Passeword: string,
public ConfirmPasseword: string
)
}
I find where is my error I used template driven and reactive forms together
this why i had error (after i read the comment of Alex )
the solution is just to remove all template driven from my Html template
<form class="col s12" [formGroup]="userLoginForm" (ngSubmit)="saveUserLogin()">
<div class="row">
<div class="input-field col s12 m6">
<input id="firstName"
type="text"
class="validate"
//[(ngModel)]="user.FirstName" ==> to remove template driven
formControlName="FirstName" //==> to keep reactive forms
// #FirstName="ngModel" ===> to remove template driven
/>
<label for="firstName">{{ 'FIRST_NAME' | translate:param }}</label>
<p class="data-error data-validation" *ngIf="FirstName.errors?.minlength">
min length is 4 caracters.
</p>
<p class="data-error data-validation" *ngIf="FirstName?.touched">
touched.
</p>
</div>
</div>
</form>
also im my
LoginComponent.ts
import {FormBuilder,FormGroup,FormControl,Validators} from '#angular/forms'
==> remove import NgForm no need with reactive forms
In the line
#FirstName="ngModel"
The component referenced needs to have defined "exportAs" value.
For example
#Directive({
selector: '[tooltip]',
exportAs: 'tooltip'
})
#FirstName="tooltip"
https://netbasal.com/angular-2-take-advantage-of-the-exportas-property-81374ce24d26
I would really like some advice and opinion I am now currently inserting data from firebase using angular. I can now insert data but the problem is It won't insert inside the child I' am calling.
This is my task-form.component.html:
<form #t="ngForm" (ngSubmit)="add(t.value)">
<div class="form-group">
<label for="taskTechiciansName">Technicians Name</label>
<select ngModel name="taskTechniciansName" id="taskTechniciansName"
class="form-control">
<option value=""></option>
<option *ngFor="let a of techNames$ | async" [value] ="a.$key">
{{ a.name }}
</option>
</select>
</div>
<div class="form-group">
<label for="taskAdd">Address</label>
<input ngModel name="taskAdd" id="taskAdd" type="text" class="form-control">
</div>
<div class="form-group">
<label for="taskDate">Date</label>
<input ngModel name="taskDate" id="taskDate" type="date" class="form-control">
</div>
<div class="form-group">
<label for="taskClass">Class</label>
<input ngModel name="taskClass" id="taskClass" type="text" class="form-control">
</div>
<div class="form-group">
<label for="taskDesc">Description</label>
<input ngModel name="taskDesc" id="taskDesc" type="text" class="form-control">
</div>
<button class="btn btn-primary">Add Task</button>
</form>
here is my code tasks.service.ts:
import { Injectable } from '#angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFireDatabaseModule } from 'angularfire2/database';
#Injectable()
export class TaskService {
uid: string;
constructor(private db: AngularFireDatabase,
private af: AngularFireDatabase,
private am: AngularFireAuthModule
) {
}
create(tasks){
return this.db.database.ref('/users/').push({ tasks }).key;
}
}
and this is my database structure:
and this is how the data is being submitted:
task data
I really want to insert the info data into a specific user under tasks child. Your help is greatly appreciated.
The first mistake is a simple typo: you're missing a / in the path:
create(tasks){
return this.db.database.ref('/users/' + this.uid).push({ tasks }).key;
}
The second mistake is just as simple: you never give uid a value, so it's undefined. I'm just not sure how to fix it, since it depends on what you're trying to accomplish.
I'm starting with Angular and I'm on a project where I have to validate the inputs so they can't be left clear, every input must me completed.
It's an html and we have a .ts file.
This is an extract of the html:
<div class="form-group">
<input type="text"
class="form-control"
id="factory"
[(ngModel)]="factory.company">
</div>
I need to validate this factory input but when I was watching tutorials all I needed to do was to write 'required' inside the <input> and that was it but I had a <form> and every input was inside this form, and this html doesn't have a <form> and when I put one the design was horrible and I couldn't work.
Here is an example using required fields (in login page) :
<form [formGroup]='loginForm' (submit)="login(loginForm.value)">
<div class="col-md-6">
<div class="login-mail">
<input type="text" placeholder="Email" formControlName="email" required="">
<i class="fa fa-envelope"></i>
</div>
<div class="login-mail">
<input type="password" placeholder="Password" formControlName="password" pattern=".{8,20}" required="">
<i class="fa fa-lock"></i>
</div>
</div>
<div class="col-md-6 login-do">
<label class="hvr-shutter-in-horizontal login-sub">
<input type="submit" value="login" >
</label>
</div>
<div class="clearfix"> </div>
</form>
in the login.component.ts , u should make some changes:
1) import some modules :
import { FormBuilder, FormGroup, Validators} from '#angular/forms';
2) in oninit function :
loginForm: FormGroup;
constructor(private fb : FormBuilder) {}
ngOnInit(){
this.loginForm = this.fb.group({
email : ["", Validators.required],
password : ["", Validators.required]
});
}
Hope that helps u :)
I would think that you should be able to add a form element. However, if you cannot as you have said then you can add the ngForm directive onto any element to achieve the same behavior as having the form element.
See this plunker for examples using ReactiveFormsModule and FormsModule:
Plunker
//our root app component
import {Component, OnInit, NgModule} from '#angular/core'
import {ReactiveFormsModule, FormsModule, FormControl, Validators} from '#angular/forms'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div class="form-group">
<label>Model Driven Form</label>
<input type="text"
class="form-control"
id="companyModel"
[formControl]="companyModel">
<span [hidden]="companyModel.valid || companyModel.pristine">REQUIRED!</span>
</div>
<div class="form-group" ngForm #myForm="ngForm">
<label>Template Driven Form</label>
<input type="text"
class="form-control"
name="companyTemplate"
ngModel
id="companyTemplate"
#companyTemplate="ngModel"
required>
<span [hidden]="companyTemplate.valid || companyTemplate.pristine">REQUIRED!</span>
</div>
</div>
`,
})
export class App implements OnInit {
name:string;
companyModel: FormControl
constructor() {
this.name = 'Form Validation Demo'
}
ngOnInit() {
this.companyModel = new FormControl('', Validators.required)
}
}
#NgModule({
imports: [ BrowserModule, ReactiveFormsModule, FormsModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
This is to some extent a dupe of this question but hopefully less convoluted.
Is it possible to to add a completely new FormGroup via a form input where the new FormGroupName can be defined via input? If so which directives or functions would I use to achieve this?
User Case:
The user can define a new FormGroupName via input field and click to extend the form with the new FormGroup, then fill out values for that FormGroup’s FormControls.
1 User fills out an existing 'name' field as normal.
2 Types ‘foo’ into an input field
3 Clicks ‘add data group’ to create the new FormGroup 'foo'
4 The form reveals input fields for 'height' and 'weight' for the new FormGroup foo.
5 User fills out 'height' and 'weight' values for 'foo'
6 Repeats step 2-5 for 'bar'
7 Submits:
{
"name":"Data Form",
"foo":{
"height":"6.00",
"weight":"300"
},
"bar":{
"height":"5.11",
"weight":"260"
}
}
The FormControls in the added FormGroups will always be consistent.
So as in the above example always ‘weight’ and ‘height’.
The intention is to use the form as a basic UI to help generate some JSON data.
Thanks.
The solution I came up with was to use a dynamic [formGroupName] which references an array which is updated each time a new group is added
[formGroupName]="myGroupName[i]"
app.component.ts :
import { Component, OnInit } from '#angular/core';
import { Customer } from './customer.interface';
import { FormControl, FormBuilder, FormGroup, FormArray, Validators } from '#angular/forms';
#Component({
moduleId: module.id,
selector: 'my-app',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
public myForm: FormGroup;
myGroupName = ['test'];
constructor(private _fb: FormBuilder) {
}
ngOnInit() {
this.myForm = this._fb.group({
myArray: this._fb.array([
this._fb.group({
test: this._fb.group({
name: ['test'],
title: [''],
link: [''],
cta: [''],
})
}),
])
});
}
initArray(nameObj:any) {
return this._fb.group({
[nameObj]: this._fb.group({
name: [nameObj],
title: [''],
link: [''],
cta: [''],
})
})
}
addArray(newName:string) {
const control = <FormArray>this.myForm.controls['myArray'];
this.myGroupName.push(newName);
control.push(this.initArray(newName));
document.getElementById('newName').value='';
}
removeDataKey(i: number) {
const control = <FormArray>this.myForm.controls['myArray'];
control.removeAt(i);
this.myGroupName.splice(i,1);
}
}
app.component.html:
<form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm)">
<div formArrayName="myArray">
<div *ngFor="let myGroup of myForm.controls.myArray.controls; let i=index" class="panel panel-default">
<div [formGroupName]="i" class="panel-body">
<span *ngIf="myForm.controls.myArray.controls.length > 1"
(click)="removeDataKey(i)" class="glyphicon glyphicon-remove pull-right">
</span>
<h5 >Group {{i + 1 }}</h5>
<h3> {{myGroupName[i] }}</h3>
<!--[formGroupName]="myGroupName[i]"-->
<div [formGroupName]="myGroupName[i]" class="panel-body">
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" formControlName="title" >
</div>
<div class="form-group">
<label>Link</label>
<input type="text" class="form-control" formControlName="link" >
</div>
<div class="form-group">
<label>Cta</label>
<input type="text" class="form-control" formControlName="cta" >
</div>
</div>
<!--[formGroupName]="myGroupName[i]"-->
</div>
<!--[formGroupName]="i" -->
</div>
</div>
<!-- myArray array-->
<div class="margin-20">
<input #newName
(keyup.enter)="addName(newName.value)"
type="text" style="width:30%" id="newName">
<a (click)="addArray(newName.value)" style="cursor: default" class="btn">Add Group +</a>
</div>
</form>
The dupe of this question is also answered here with related plunks