Input fields as lists in Angular - html

I want to take inputs from the user and append them to a list I have in my typescript. Here's what I have tried so far.
Here's the code:
<input type="text" id="course" name="course" class="form-control"[(ngModel)]="institutes.course">
institutes={course:''}

Use a function to add a new course and trigger it using a button.
app.component.html :
<!-- Input field -->
<input type="text" id="course" name="course" class="form-control" [(ngModel)]="newCourse">
<!-- Add button -->
<button (click)="addCourse()">Add</button>
app.component.ts :
newCourse : string = '';
allCourses : string[] = [];
// Function to add course
addCourse(){
this.allCourses.push(this.newCourse);
//Reset input
this.newCourse = '';
}
Demo : https://stackblitz.com/edit/angular-hzh42b

Write the following method in your component -
constructor(private url: string, private http: HttpClient) {}
posts: any;
createPost(input: HTMLInputElement) {
const post = { title: input.value };
this.posts.splice(0, 0, post);
input.value = "";
this.service.create(post).subscribe(
newPost => {
post.id = newPost;
},
(error: AppError) => {
this.posts.splice(0, 1);
if (error instanceof BadInput) {
// this.form.setErrors(error.originalError);
} else {
throw error;
}
}
);
}
Include this method in your service -
constructor(private url: string, private http: HttpClient) {}
create(resource) {
return this.http.post(this.url, JSON.stringify(resource)).pipe(
map(response => response),
catchError(this.handleError)
);
}
write the following code in your HTML -
<input
(keyup.enter)="createPost(title)"
#title
type="text"
class="form-control"
/>
You are good to go now!

The following code will help you to add a course into a list, which will be displayed in the web page.
.ts
courseList contains a list of all the added courses
course is the current course that you are adding.
addCourse is a method which will add a course into the list, and clear the course string.
public courseList = [];
public course;
addCourse() {
this.courseList.push(this.course);
console.log(this.courseList);
this.course = '';
}
.html
There is an input field which will take in course name.
And an add course button which will add the entered course name into the list and display the course list in the web page.
<ul>
<li *ngFor="let course of courseList">
{{course}}
</li>
</ul>
<input type="text" id="course" name="course" class="form-control" [(ngModel)]="course">
<button (click)="addCourse()">Add Course</button>

Related

ERROR TypeError: can't assign to property "validator" on "12345": not an object

I want to build a pre filled form, as of now I am getting this error when i try to display the form page. I have tried various solutions that was given but that doesn't seem to work here.
My hardwareRequest.ts
hardwareReviewForm: FormGroup;
assetSerialNumber = new FormControl('');
modelType = new FormControl('');
ngOnInit(): void {
this.data = []
this.service.loadRequestData(this.requestId).subscribe(
(response: any) => {
this.data = response
console.log(this.data)
this.assetSerialNumber = this.data.assetSerialNumber
this.modelType = this.data.modelType
},
(error) => {
}
)
}
My HTML file
<form class="example-container" [formGroup]="hardwareReviewForm" (ngSubmit)="onFormSubmit()">
<div class="ds-col-12" style="margin-bottom: 10px;">
<div class="ds-col-6">
<mat-form-field appearance="outline">
<mat-label>Asset Serial Number: </mat-label>
<input formControlName="assetSerialNumber" readonly matInput type="text">
</mat-form-field>
</div>
<div class="ds-col-6">
<mat-form-field appearance="outline">
<mat-label>Part No./Model Type: </mat-label>
<input formControlName="modelType" readonly matInput type="text">
</mat-form-field>
</div>
</div>
</form>
You can make a 'View Model' of your fields and then reset your form with it.
export class testVm {
assetSerialNumber : number;
modelType : string;
}
var model: testVm = this.data;
this.hardwareReviewForm.reset(model)
Or if you want to assign value separately you should act like this:
this.hardwareReviewForm.controls["assetSerialNumber"].reset(this.data.assetSerialNumber.toString())
Firstly, you have to define form controls inside formGroup;
hardwareReviewForm = new FormGroup({
assetSerialNumber = new FormControl('');
modelType = new FormControl('');
});
Secondly, you set the values to controls like below;
this.hardwareReviewForm.get('assetSerialNumber').setValue(this.data.assetSerialNumber);
I figured this out.. It was a silly mistake of .setValue for form controls.
setting my value like below works fine.
this.Number.setValue(this.data.Number)
this.Type.setValue(this.data.Type)

HTML Dropdown disappears after a value is set to null in Angular

I have two values power and mainPower which describe the same thing but mainPower saves an id of type Long in the backend and power saves all attributes of this dto. With the code below I can update a hero's power, meaning I can change it from something to the other and also make it null (meaning no power).
The problem is that when a power is set to null or it was null before, the dropdown menu disappears. I don't want the dropdown to disappear, I just want it to say "no power" when it is null and I should be able to change it from null to something.
hero-detail.component.html
<form #heroUpdateForm = "ngForm">
{{diagnostic}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
required
*ngIf="hero" [(ngModel)]="hero.name" name="name">
</div>
<div class="form-group">
<label for="desc">Description</label>
<input type="text" class="form-control" id="desc"
*ngIf="hero" [(ngModel)]="hero.desc" name="desc">
</div>
<div class="form-group" *ngIf="hero?.power">
<label for="power">Main Power</label>
<select class="form-control" id="power"
required
[(ngModel)]="hero.mainPower" name="power">
<option [ngValue]="null">no power</option>
<ng-container *ngFor="let power of powers">
<option [value]="power.id">{{power.name}}</option>
</ng-container>
</select>
</div>
</form>
hero-detail.component.ts
export class HeroDetailComponent implements OnInit {
public heroes: Hero[];
public powers: Power[];
submitted = false;
private hero: Hero;
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private powerService: PowerService,
private location: Location,
private router: Router
) {}
ngOnInit(): void {
this.getHero();
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.getHeroes();
this.getPowers();
}
getHero(): void{
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id).subscribe(
(hero: Hero) => {
this.hero = hero;
if (hero.power != null) {
this.powerService.getPowerById(hero.power).subscribe(
(powerResponse) => {
hero.power = powerResponse;
}
);
}
});
}
public getHeroes(): void {
this.heroService.getHeroes().subscribe(
(response: Hero[]) => {
this.hero = response;
},
(error: HttpErrorResponse) => {
alert(error.message);
}
);
}
public getPowers(): void {
this.powerService.getAllPowers().subscribe(
(response: Power[]) => {
this.power = response;
},
(error: HttpErrorResponse) => {
alert(error.message);
}
);
}
goBack(): void {
this.location.back();
}
save(): void {
this.heroService.updateHero(this.hero, this.hero.id)
.subscribe(() => this.goBack());
}
onSubmit() {this.submitted = true;}
get diagnostic() {return JSON.stringify(this.hero);}
Is obvious why it'll disappear, look at your template again:
<div class="form-group" *ngIf="hero?.power"> <!-- lookie here, if either hero or power is null this element along with everything in it will be gone!! -->
<label for="power">Main Power</label>
<select class="form-control" id="power" <!-- your select is inside the div above with the ng if -->
required
[(ngModel)]="hero.mainPower" name="power">
<option [ngValue]="null">no power</option>
<ng-container *ngFor="let power of powers">
<option [value]="power.id">{{power.name}}</option>
</ng-container>
</select>
essentially the ngIf you have in the div surrounding the select element says the following:
if(ngIf) hero and power -> display element
if(ngIf) no hero and power -> remove element
You might not want to have *ngIf="hero?.power" perhaps you should just check if there is a hero *ngIf="hero" instead

Activating separate functions based on the result of a function that posts information from a Form

I'm a bit of a novice with the implementation of multiple functions. However, I have a form where people can enter information which when submitted is posted to where I am collating the information. My code at the moment is:
component.html
<form name="hello"(ngSubmit)="onSubmit(helloForm); helloForm.reset();closeModal('custom-modal-2');openModal('custom-modal-3')" #helloForm="ngForm">
<input type="text" class = "box" placeholder="Name" name="name" ngModel required #name="ngModel"><br>
<input type="text" class = "box" placeholder="Email" email name="email" ngModel required #email="ngModel">
<re-captcha (resolved)="resolved($event)" siteKey="key"></re-captcha>
<br><input class="submit" type="submit" value="Submit">
</form>
component.ts
export class HelloDetailsComponent {public pageTitle = 'Contact Me';
constructor(private modalService: ModalService, private http: HttpClient) {}
resolved(captchaResponse: string) {
console.log(`Resolved captcha with response: ${captchaResponse}`);
}
openModal(id: string) {
this.modalService.open(id);
}
closeModal(id: string) {
this.modalService.close(id);
}
onSubmit(helloForm: NgForm) {
if (helloForm.valid) {
const email = helloForm.value;
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
this.http.post('formsent',
{Name: email.name, Email: email.email},
{ 'headers': headers }).hello(
response => {
console.log(response);
}
);
}
}
At the moment, when I press the submit button without filling out the form, the openModal('custom-modal-3') appears.
I would like to change this so that it only appears when the form is submitted and implement a separate modal for when the form is incomplete. Does anyone have any ideas?

Is there a way to save the data from dropdownlist-input field?

So I have this HTML field where I can Input some text. I can send it to API and it has no problem with it. However is it possible to have the input field as a dropdown list and get the same outcome?
I have tried one way, but I cant still bind 2 properties into my NgModel to get the data going into my API. So I had these hardcoded lists in my .ts file to test if this method works. I get the value into my input field, but I cannot send it to API.
HTML
<div fxLayout="row" fxLayoutAlign="center start">
<div fxLayout="column" class="term-detail">
<ejs-dropdownlist [dataSource]='data' [(value)]='value' placeholder='Select a Term'></ejs-dropdownlist>
<div style='margin-top: 50px'>
<input matInput type="text" [(ngModel)]="value" />
</div>
</div>
</div>
<button (click)="onSave()">Tallenna</button>
TYPESCRIPT FILE
export class SelectTermComponent implements OnInit {
terms: Term;
constructor(private service: TermService, private httpService: TermHttpService, private router: Router ) {
this.terms = new Term();
}
public data: string[] = ['Test 1', 'Test 2', 'Test 3', 'Test 4'];
public value: 'Badminton';
ngOnInit() {
}
onSave() {
console.log('data sent to DB!');
this.httpService.create(this.terms).subscribe(result => {
console.log(result);
});
this.router.navigate(['termselected']);
console.log('navigated to termSelected');
}
This is how it works without the dropdownlist select:
<mat-form-field floatPlaceholder="auto">
<input matInput [(ngModel)]="terms.source" required
placeholder="Lähtökäsite">
</mat-form-field>
Term.ts
export class Term {
termId: number;
termValue: string;
termArrow: string;
source: number;
target: number;
constructor(termId?: number, termValue?: string, termArrow?: string, source?: number, target?: number) {
this.termId = termId;
this.termValue = termValue;
this.termArrow = termArrow;
this.source = source;
this.target = target;
}
}
I expect the data to go into the API but since ngModel has the 'value' binding instead of 'term.x' I think it is not the way it should be. Any ideas?

Angular2 Edit profile: Display retrieved data in HTML input tag

I have an edit profile page. So when the user clicks on the edit profile page the users details should be displayed in the input tag fields in the HTML. But I am unable to display the details I am retrieving.
edit-profile.component.html
<form novalidate (ngSubmit)="onFormSubmit(signupForm)" #signupForm="ngForm">
<div class="form-inputs clearfix">
<div class="row">
<div class="col-md-6">
<p>
<label class="required">First Name<span>*</span></label>
<input
type="text"
[value]="accountDetails.firstName"
name="firstName"
[(ngModel)] = "user.firstName"
#firstName = "ngModel"
required><p>{{accountDetails.firstName}} </p>
<span *ngIf="firstName.invalid && (firstName.dirty || firstName.touched)" class="input-error">
<span *ngIf = "firstName.errors?.required">
First Name field can't be blank
</span>
</span>
</p></form>
edit-profile.component.ts
import { Component, OnInit } from '#angular/core';
import { ApiServiceProvider } from '../services/api.service';
#Component({
selector: 'app-edit-profile',
templateUrl: './edit-profile.component.html',
styleUrls: ['./edit-profile.component.css']
})
export class EditProfileComponent implements OnInit {
public user: any = {};
public accountDetails: any = {}
constructor(
private api: ApiServiceProvider
) { }
ngOnInit() {
let profile = JSON.parse(localStorage.getItem("profile"));
this.accountDetails = profile.user;
console.log(this.accountDetails);
}
public onFormSubmit({ value, valid }: { value: any, valid: boolean }) {
this.user = value;
this.api.put("/users/editprofile", value.userId, false)
.subscribe((data) => {
console.log(data)
localStorage.setItem("profile", JSON.stringify(data));
location.href = "/profile"
}, (err) => {
alert("Registartion failed " + err);
})
}
}
you only populate your accountDetails variable but you try to bind your user variable.
so you have:
this.accountDetails = profile.user;
but you bind your input to the user variable:
<input type="text" [(ngModel)]="user.firstName" #firstName="ngModel" required>
Either populate your user variable:
this.user = profile.user;
or bind to your account details variable:
<input type="text" [(ngModel)]="accountDetails.firstName" #firstName="ngModel" required>
Also you need to close your div clearfix, div row and div column correctly before closing the form tag. </div></div></div></form>