Skip to content

Instantly share code, notes, and snippets.

@obumnwabude
Created March 26, 2022 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save obumnwabude/38a2fb529bcf0f3b885ab9b33458729b to your computer and use it in GitHub Desktop.
Save obumnwabude/38a2fb529bcf0f3b885ab9b33458729b to your computer and use it in GitHub Desktop.
Angular Form for managing questions and their answers
<mat-toolbar class="mat-elevation-z1" id="navbar">
<span>Questions</span>
</mat-toolbar>
<form [formGroup]="questionForm" (ngSubmit)="onSubmit()">
<mat-form-field>
<mat-label>Question</mat-label>
<textarea matInput required formControlName="value"></textarea>
<mat-error> Question is <strong>required</strong> </mat-error>
</mat-form-field>
<div id="correct-option">
<h5>Correct Option</h5>
<mat-radio-group color="primary" formControlName="correct">
<mat-radio-button
*ngFor="let option of options; index as i"
[value]="option"
[checked]="i === 0"
>{{ option }}</mat-radio-button
>
</mat-radio-group>
</div>
<mat-form-field *ngFor="let option of optionControls">
<mat-label>Option {{ option.get('index')?.value }}</mat-label>
<textarea
matInput
required
[formControl]="$any(option.get('value'))"
></textarea>
<mat-error>
Option {{ option.get('index')?.value }} is <strong>required</strong>
</mat-error>
</mat-form-field>
<div id="update-btn-container">
<button mat-raised-button color="primary" type="submit">Update</button>
</div>
</form>
mat-toolbar#navbar {
position: fixed;
top: 0;
z-index: 2;
}
form {
padding: 96px 32px 32px 32px;
max-width: 384px;
margin: 0 auto;
}
mat-form-field {
display: block;
}
#correct-option {
display: inline-block;
margin-right: 32px;
margin-bottom: 32px;
}
mat-radio-button {
margin-right: 16px;
}
#update-btn-container {
text-align: right;
}
import { Component } from '@angular/core';
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
options = ['A', 'B', 'C', 'D'];
questionForm: FormGroup = new FormGroup({
value: new FormControl('', Validators.required),
correct: new FormControl(this.options[0], Validators.required),
options: new FormArray(
this.options.map(
(o) =>
new FormGroup({
index: new FormControl(o, Validators.required),
value: new FormControl('', Validators.required)
})
)
)
});
get optionControls() {
return (this.questionForm.get('options') as FormArray)
.controls as FormGroup[];
}
constructor(private snackBar: MatSnackBar) {}
onSubmit(): void {
if (this.questionForm.valid) {
console.log(this.questionForm.value);
this.snackBar.open('Question successfully submitted.', '', {
panelClass: ['snackbar-success']
});
} else {
this.snackBar.open('Please fill all the required fields.', '', {
panelClass: ['snackbar-error']
});
}
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import {
MatFormFieldModule,
MAT_FORM_FIELD_DEFAULT_OPTIONS
} from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRadioModule } from '@angular/material/radio';
import { MatSnackBarModule, MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
import { MatToolbarModule } from '@angular/material/toolbar';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
ReactiveFormsModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatSnackBarModule,
MatToolbarModule,
MatRadioModule
],
providers: [
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: { appearance: 'outline' }
},
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: { duration: 5000, verticalPosition: 'top' }
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
snack-bar-container.mat-snack-bar-container {
display: flex;
align-items: center;
}
.snackbar-success,
.snackbar-error {
color: #fff; // make the text clearer
}
.snackbar-success::before {
font-family: 'Material Icons';
content: '\f013'; // icon for gpp_good
color: #9ce2b6; // green
margin-right: 8px;
}
.snackbar-error::before {
font-family: 'Material Icons';
content: '\e000'; // icon for error
color: #fc9494; // red
margin-right: 8px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment