I wrote some code in TypeScript for Angular 2. When I click on submit button, the data is appending to the database but the values that appears in the database is wrong
At one click, my database has 4 rows inserted with 1 row valid data and other 3 with null values.
This is my component:
import {Component} from '#angular/core';
import {Http, Response, Headers} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import {Subject } from 'rxjs/Subject';
#Component({
templateUrl: './components/profile/profile.html'
})
export class Profile {
http: Http;
constructor(http: Http) {
this.http = http;
}
postResponse = new Person();
onSubmit(form){
//this.form = form;
console.log(form);
var headers = new Headers();
// headers.append('Content-Type', 'application/json');
headers.append('Content-Type','application/x-www-form-urlencoded')
this.http.post('http://localhost/fin/index.php/profile/addprofile', JSON.stringify(form),{headers:headers})
.map((res: Response) => res.json())
.subscribe((res:Person) => this.postResponse = res);
}
}
class Person {
firstName:string;
lastName:string;
}
My template
<h3 class= "head">MY PROFILE</h3>
<form (ngSubmit)="onSubmit(myForm.value)" #myForm="ngForm" >
<div class="form-row">
<div class="col-lg-6" >
<div class="formHeading get">First Name</div>
<input type="text" id="firstName" class = "col-sm-7" ngControl="firstname">
</div>
<div class="form-row">
<div class="col-lg-6" >
<div class="formHeading get" >Last Name</div>
<input type="text" id="firstName" class = "col-sm-7" ngControl="lastname">
<div class="form-row">
<div class="col-lg-6" >
<div class="formHeading get">Email</div>
<input type="text" id="zip" class = "col-sm-7" ngControl="email">
<div class="form-row">
<div class="col-lg-6" >
<div class="formHeading get">Profile Name</div>
<input type="text" id="profileName" class = " col-sm-7" ngControl="profilename">
<div class="form-row">
<div class="col-lg-6" >
<div class="formHeading get">Contact Number</div>
<input type="text" id="firstName" class = " col-sm-7" ngControl="phone">
Save
I am not sure where the error is about and sometimes I see the correct data in the database and sometimes not. Can anyone find the error?
Related
I am attempting to pass the function submitForm from formControl to index.js (Home). My goal: to remove form, upon successful form submission and show a success message. I have looked at several examples, but I am still missing something.
I am using Next.js, but I don't think the Next.js usage would be any different from react.js in this case. Also using react-hook-form, once again, I don't think RHF is interrupting the process.
index.js Home view
import { useState } from 'react';
import { useForm } from "react-hook-form";
import styles from '../styles/Home.module.css'
import { proteinArr, starchArr, greensArr} from '../utils'
import date from 'date-and-time';
export default function Home({ submitForm }) {
const { register, handleSubmit, control, formState: { errors } } = useForm();
const onSubmit = (data, e) => {
e.target.reset()
submitForm()
}
const now = new Date();
let day = date.format(now, 'dddd').toLowerCase();
// console.log(SaturdayArr)
// console.log(date.format(now, 'dddd').toLowerCase())
return (
<>
<form onSubmit={handleSubmit((onSubmit))}>
<div className={`${styles.home_card} card home_card `}>
<div className="card-body">
<h2 className={styles.title}>Pick your plate!</h2>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Name</span>
</div>
<input type="text" className="form-control" {...register("name", { required: true })} placeholder="Order Name" aria-label="Order Name" aria-describedby="basic-addon" />
{errors.name && <p>Order name is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Email</span>
</div>
<input type="email" id="email" className="form-control" {...register("email")} placeholder="Email#provider.com" aria-label="Email" aria-describedby="basic-addon" />
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<span className="input-group-text" >Phone Number</span>
</div>
<input type="tel" id="phone" className="form-control" {...register("phone", { required: true })} placeholder="111-111-1111" aria-label="Phone Number" aria-describedby="basic-addon" />
{errors.name && <p>Phone number is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Protein</label>
</div>
<select {...register("protein", { required: true })}
className={`${styles.home_select} custom-select" id="inputGroupSelect01`}
>
<option className={styles.home_option}>Choose...</option>
{proteinArr && proteinArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.protein && <p>Protein is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Greens</label>
</div>
<select
{...register("greens", { required: 'select an option' })}
className={`${styles.home_select} custom-select" id="inputGroupSelect01`}>
<option className={styles.home_option}>Choose...</option>
{greensArr && greensArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.greens && <p>Green is required</p>}
</div>
<div className={`${styles.home_selectGroup} input-group mb-3`}>
<div className="input-group-prepend">
<label className={`${styles.homeLabel} input-group-text`} htmlFor="inputGroupSelect01">Starch</label>
</div>
<select {...register("starch", { required: true })} className={`${styles.home_select} custom-select" id="inputGroupSelect01`}>
<option className={styles.home_option}>Choose...</option>
{starchArr && starchArr.map((item) => <option key={item}>{item}</option>)}
</select>
{errors.starch && <p>Starch is required</p>}
</div>
<button className="btn btn-primary contact-form_button " type="submit">Submit My Order</button>
</div>
</div>
</form>
</>
)
}
FormControl
import Home from '../../pages/index'
import { useState } from 'react';
const FormControl = () => {
const [isSubmitted, setIsSubmitted] = useState(false);
function submitForm(){
setIsSubmitted(true);
}
return (
<div>
{isSubmitted == false ? <Home submitForm={submitForm}/> : <h2>Your from was submitted</h2>}
</div>
);
}
export default FormControl;
Next.js is just logic on top of React so the way you interact with it is handled the same for both libraries.
However, pages in React and Next.js are both components but pages in Next.js have a lot of functionality added/injected, so you must treat them differently.
Because of this, you cannot just pass props to pages in Next.js like you are as they will always be undefined. You can set page props via getInitialProps, getStaticProps, getServerSideProps, in _document, or even in _app.
With that said, you can simplify your form status by using react-hook-form's successful form submission status.
export default function Home() {
const {formState: { isSubmitSuccessful } } = useForm();
if(isSubmitSuccessful) return <h2>Your from was submitted</h2>;
<form onSubmit={handleSubmit((onSubmit))}>
...form stuff
</form>
}
You could make the form it's own component too
Home page
import HomeForm form './HomeForm'
export default function Home() {
handleSubmit= () => {...submit logic}
return <HomeForm onSubmit={handleSubmit} />
}
Home form component
export default function HomeForm({ onSubmit }) {
const {formState: { isSubmitSuccessful } } = useForm();
if(isSubmitSuccessful) return <h2>Your from was submitted</h2>;
<form onSubmit={handleSubmit((onSubmit))}>
...form stuff
</form>
}
I want to display my object values in HTML tags but nothing comes up. The object appears successfully in the console. When I simply place res only [object object] displays on the page and res.json and res.text display nothing. Please see code below.
Shopping-Cart-Child.component.html
<form #form="ngForm" autocomplete="off">
<div class="form-group">
<div class="input-group">
<div class="input-groupprepend">
<div class="input-group-text bg-white">
<i class="fas fa-user-tie"></i>
</div>
</div>
<input placeholder="Person Number" type="text" [(ngModel)]=personNo name="personNo">
</div>
</div>
<br>
<div class="form-group">
<button class="btn btn-success btn-lg btn-block" (click)=SearchCustomer()>Get shopping cart</button>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-7">
<p>{{results}}</p>
</div>
</div>
</div>
</form>
Shopping-cart-child.Component.ts
import { Component, OnInit } from '#angular/core';
import {HttpClient,HttpResponse} from '#angular/common/http';
#Component({
selector: 'app-shopping-cart-child',
templateUrl: './shopping-cart-child.component.html',
styles: [
]
})
export class ShoppingCartChildComponent implements OnInit {
personNo=''
results:any;
constructor(private http:HttpClient) { }
SearchCustomer(){
return this.http.get("http://lab.tekchoice.co.za/api/v1/CCWeb/GetShoppingCart?accountNo="+this.personNo)
.subscribe((res:Response)=>{
console.log(res);
this.results = res.json;
}
)
}
ngOnInit(): void {
}
}
Use the json pipe.
E.g.
<p>{{results | json}}</p>
I'mm creating an Angular application with ASP.NET.
I need to create:
courses,
course contents
course schedules for the selected course.
After creating the course I will select that particular course and create the content for that.
But while submitting the form, I also need to save the selected course id as a foreign key in database.
Can anyone help me on this please?
createcontent.component.ts
import { Component, OnInit, EventEmitter, Output } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { CoursesService } from 'src/app/shared/courses.service';
import { Content } from '#angular/compiler/src/render3/r3_ast';
import {ActivatedRoute} from '#angular/router';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-createcontent',
templateUrl: './createcontent.component.html',
styleUrls: ['./createcontent.component.css']
})
export class CreatecontentComponent implements OnInit {
contentForm: FormGroup;
contents:Content[];
courseName: string;
courseid;
isSubmitted:boolean;
constructor(private courseservice:CoursesService,private fb: FormBuilder,private route:ActivatedRoute,private http:HttpClient) {
}
setValue(){
this.contentForm.setValue({
courseid:this.route.snapshot.params['id']
});
}
ngOnInit(): void {
this.courseName=this.route.snapshot.params['cname'];
this.courseid=this.route.snapshot.params['id']
this.contentForm = this.fb.group({
contentname: ['', Validators.required ],
contentdescription: ['', Validators.required ],
duration: ['', Validators.required ],
courseid:['']
});
this.courseservice
.getContents()
.subscribe((data: Content[]) => {
this.contents = data;
});
}
OnSubmit(){
console.log(this.contentForm);
this.http.post('https://localhost:44319/api/contents1',this.contentForm.value,this.courseid).subscribe(data=>{
console.log(data);
})
}
}
createtraining.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { CoursesService } from 'src/app/shared/courses.service';
import { Course } from 'src/app/shared/course.model';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-createtraining',
templateUrl: './createtraining.component.html',
styleUrls: ['./createtraining.component.css']
})
export class CreatetrainingComponent implements OnInit {
courseForm: FormGroup;
courses: Course[];
loading:false;
toggleState:boolean= false;
coursename = 'angular';
clickedCourse:string;
dayFinished:boolean=true;
constructor(private courseservice:CoursesService,private fb: FormBuilder,private http:HttpClient) {
}
getCourse(course:string){
this.clickedCourse=course;
}
ngOnInit(): void {
this.courseForm = this.fb.group({
coursename: ['', Validators.required ],
coursedescription: ['', Validators.required ]
});
this.courseservice
.getCourses()
.subscribe((data: Course[]) => {
this.courses = data;
this.toggleState=true;
});
}
OnSubmit(){
console.log(this.courseForm);
this.http.post('https://localhost:44319/api/courses',this.courseForm.value).subscribe(data=>{
console.log(data);
})
}
}
cretecontent.component.html
<div id="training-page" class="row">
<div class="col s8 offset-s2">
<div class="card">
<div class="sm-jumbotron center-align">
<h2>Create Content for {{courseName}}</h2>
</div>
</div>
<div class="card">
<form [formGroup]="contentForm" novalidate (ngSubmit)="OnSubmit()">
<div class="row"></div>
<div class="input-field col s6">
<input name="course_name" id="register-firstname" formControlName="contentname" type="text" class="form-input form-control" #contentname>
<label for="course_name" class="center-align">Topic Name<span class="required">*</span></label>
<div *ngIf="contentForm.controls['contentname'].invalid && (contentForm.controls['contentname'].dirty || contentForm.controls['contentname'].touched)">
<div *ngIf="contentForm.controls['contentname'].errors.required" style="color: red;font-size: 11px;">
Topic Name is required.
</div>
</div>
</div>
<div class="input-field col s6">
<input name="coursedesc" id="course-description" type="text" formControlName="contentdescription" class="form-input form-control" #contentdescription>
<label for="course_description" class="center-align">Topic Description<span class="required">*</span></label>
<div *ngIf="contentForm.controls['contentdescription'].invalid && (contentForm.controls['contentdescription'].dirty || contentForm.controls['contentdescription'].touched)">
<div *ngIf="contentForm.controls['contentdescription'].errors.required" style="color: red;font-size: 11px;">
Topic Description is required.
</div>
</div>
</div>
<div class="input-field col s6">
<input name="contenttime" id="course-description" type="text" formControlName="duration" class="form-input form-control" #duration>
<label for="course_description" class="center-align">Duration<span class="required">*</span></label>
<div *ngIf="contentForm.controls['duration'].invalid && (contentForm.controls['duration'].dirty || contentForm.controls['duration'].touched)">
<div *ngIf="contentForm.controls['duration'].errors.required" style="color: red;font-size: 11px;">
Duration is required.
</div>
</div>
</div>
<input type="text" id="courseid" formControlName="courseid" class="form-input form-control" #courseid>
<div class="row">
<div class="input-field col s12 valign center">
<button [disabled]="!contentForm.valid" (click)="setValue()" type="submit" class="btn-primary">Create</button>
</div>
</div>
</form>
</div>
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">Topic Name</th>
<th scope="col">Topic Description</th>
<th scope="col">Duration</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let content of contents">
<td>{{ content.contentname }}</td>
<td>{{ content.contentdescription }}</td>
<td>{{ content.duration}}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="input-field col s12 valign center">
<button type="button" class="btn-primary" [routerLink]="['/trainer']">Back to Course</button>
</div>
</div>
</div>
I'm coding a Employee Database in Vuejs using Firebase as my backend. On my new employee page I keep getting a 3 errors when submitting the form to add a new employee.
"Property or method "saveEmployee" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property."
"[Vue warn]: Error in v-on handler: "TypeError: _vm.saveEmployee is not a function"
"TypeError: "_vm.saveEmployee is not a function"
This is how my newemployee.vue file looks like
<template>
<div id="new-employee">
<h3>New Employee</h3>
<div class="row">
<form #submit.prevent="saveEmployee" class="col s12">
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="employee_id" required />
<label>Employee ID#</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="name" required />
<label>Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="dept" required />
<label>Department</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="position" required />
<label>Name</label>
</div>
</div>
<button type="submit" class="btn">Submit</button>
<router-link to="/" class="btn grey">Cancel</router-link>
</form>
</div>
</div>
</template>
<script>
import db from "./firebaseInit";
export default {
name: "new-employee",
data() {
return {
employee_id: null,
name: null,
dept: null,
position: null
};
},
methods: {
saveEmployee() {
db.collection("employees")
.add({
employee_id: this.employee_id,
name: this.name,
dept: this.dept,
position: this.position
})
.then(docRef => {
console.log("Client added: ", docRef.id);
this.$router.push("/");
})
.catch(error => {
console.error("Error adding employee: ", error);
});
}
}
};
</script>
The whole problem is on the saveEmployee function and I can not find a fix.
I am working on an Angular 7 application using PrimeNG and Primeflex. While trying to style a form based component, I have trouble with <input pInputText ...> elements not respecting the prime-flex styling (or at least not behaving as I would expect).
Summary of issue
(Variant 1)
I am enclosing both a <label> and <input> element in two nested <div> elements which are styled with class="p-grid" and class="p-col-*".
<div class="p-grid">
<div class="p-col-8">
<label for="description">Description</label><br/>
<input id="description" pInputText formControlName="description">
</div>
<div class="p-col-4">
<label for="numeric">Numeric</label><br/>
<input id="numeric" pInputText formControlName="numeric">
</div>
</div>
I was expecting the <input> field to grow/shrink with the available space, but it seems to have a fixed width that does not adjust to the available space or the number of columns I am using.
(Variant 2)
I then tried nesting another p-gridelement within the column-div and giving each element the full width:
<div class="p-grid">
<div class="p-col-8">
<div class="p-grid">
<label class="p-col-12" for="description">Description</label>
<input class="p-col-12" id="description" pInputText formControlName="description">
</div>
</div>
<div class="p-col-4">
<div class="p-grid">
<label class="p-col-12" for="numeric">Numeric</label>
<input class="p-col-12" id="numeric" pInputText formControlName="numeric">
</div>
</div>
</div>
This does indeed make the <input> field grow to use the available outer column space, but somehow destroys the margin between the columns/fields.
(Variant 3)
After some experimenting I have come up with a solution that does what I want, but it uses incorrect nesting of prime flex classes:
<div class="p-grid">
<div class="p-col-8">
<label class="p-col-12" for="description">Description</label>
<input class="p-col-12" id="description" pInputText formControlName="description">
</div>
<div class="p-col-4">
<label class="p-col-12" for="numeric">Numeric</label>
<input class="p-col-12" id="numeric" pInputText formControlName="numeric">
</div>
</div>
This lets the fields grow/shrink in size according to the outer column configuration and maintains the margin between fields/columns. However, as this seems to violate the nesting rules of primeflex as I understood them, I am uncertain if this is indeed the correct way to do this.
Detailed working example showing the problem
The working example can also be found on stackblitz.
Here is a complete working example, based on a default angular project (created with ng new demo):
Modifications to dependencies in package.json
(npm i --save primeflex primeicons primeng)
"primeflex": "^1.0.0-rc.1",
"primeicons": "^1.0.0",
"primeng": "^8.0.0-rc.1"
Modifications to angular.json
"styles": [
'node_modules/primeicons/primeicons.css',
'node_modules/primeng/resources/primeng.min.css',
'node_modules/primeflex/primeflex.css',
'node_modules/primeng/resources/themes/nova-light/theme.css',
"src/styles.css"
],
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import {FormsModule, ReactiveFormsModule} from '#angular/forms';
import {PanelModule} from 'primeng/panel';
import {AutoCompleteModule} from 'primeng/autocomplete';
import {BrowserAnimationsModule} from '#angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { ListComponent } from './list.component';
import { DetailComponent } from './detail.component';
import { LeftComponent } from './left.component';
import { RightComponent } from './right.component';
#NgModule({
declarations: [
AppComponent,
ListComponent,
DetailComponent,
LeftComponent,
RightComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
PanelModule,
AutoCompleteModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template: `
<ng-container>
<h3>Title</h3>
<div class="container">
<app-list></app-list>
<app-detail></app-detail>
</div>
</ng-container>`,
styles: [`
div.container {
display: flex;
flex-wrap: nowrap;
}
app-list {
flex: 0 0 auto;
}
app-detail {
flex: 1 0 auto;
}`
]
})
export class AppComponent {
title = 'demo';
}
list.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-list',
template: `
<p-panel [header]="'List'">
<div class="item" *ngFor="let item of items">
<div>{{item}}</div>
</div>
</p-panel>`
})
export class ListComponent {
items: string[] = ['Item 1', 'Item 2', 'Item 3'];
}
detail.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-detail',
template: `
<div class="left">
<p-panel [header]="'Left'">
<app-left></app-left>
</p-panel>
</div>
<app-right></app-right>`,
styles: [':host { display: flex; } div.left{ flex: 1 0 auto; padding: 0 15px; } app-right { flex: 0 1 50%; }']
})
export class DetailComponent {
}
left.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-left',
template: '<p>left works!</p>'
})
export class LeftComponent {
}
right.component.ts
(Choose which version of right*.component.html by uncommenting the correct lines. The order of these correspond to the order I used to present my three approaches above)
import { Component, OnInit } from '#angular/core';
import {FormBuilder, FormGroup} from '#angular/forms';
#Component({
selector: 'app-right',
// --> choose variant by activating one of the three following lines
templateUrl: './right1.component.html'
// templateUrl: './right2.component.html'
// templateUrl: './right3.component.html'
})
export class RightComponent implements OnInit {
form: FormGroup;
items: string[] = ['Austria','France','Germany','Italy','Liechtenstein','Switzerland'];
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.form = this.buildForm();
this.fillForm();
}
buildForm(): FormGroup {
return this.fb.group({
id1: [{value: '', disabled: true}],
id2: [{value: '', disabled: true}],
id3: [{value: '', disabled: true}],
auto: [{value: '', disabled: true}],
description: [{value: '', disabled: true}],
numeric: [{value: '', disabled: true}],
field1: [{value: '', disabled: true}],
field2: [{value: '', disabled: true}],
field3: [{value: '', disabled: true}],
field4: [{value: '', disabled: true}]
});
}
fillForm() {
this.form.controls.id1.setValue('42');
this.form.controls.id2.setValue('666');
this.form.controls.id3.setValue('314152');
this.form.controls.auto.setValue('Germany');
this.form.controls.description.setValue('Short text');
this.form.controls.numeric.setValue('2345');
this.form.controls.field1.setValue('foo');
this.form.controls.field2.setValue('bar');
this.form.controls.field3.setValue('baz');
this.form.controls.field4.setValue('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
}
}
right1.component.html (Variant 1)
<p-panel [header]="'Right 1'">
<form [formGroup]="form" class="container">
<div class="p-grid">
<div class="p-col-12">
<label for="id">ID</label>
<div>
<input pInputText id="id" formControlName="id1">
<input pInputText formControlName="id2">
<input pInputText formControlName="id3">
</div>
</div>
</div>
<h3>Grouped Information</h3>
<div class="p-grid">
<div class="p-col-12">
<label for="auto">Autocomplete</label>
<p-autoComplete
id="auto"
formControlName="auto"
[suggestions]="items"
[style]="{width: '100%'}">
</p-autoComplete>
</div>
</div>
<div class="p-grid">
<div class="p-col-8">
<label for="description">Description</label><br/>
<input id="description" pInputText formControlName="description">
</div>
<div class="p-col-4">
<label for="numeric">Numeric</label><br/>
<input id="numeric" pInputText formControlName="numeric">
</div>
</div>
<h3>More grouped information</h3>
<div class="p-grid">
<div class="p-col-3">
<label for="field1">Field 1</label><br/>
<input id="field1" pInputText formControlName="field1">
</div>
<div class="p-col-3">
<label for="field2">Field 2</label><br/>
<input id="field2" pInputText formControlName="field2">
</div>
<div class="p-col-3">
<label for="field3">Field 3</label><br/>
<input id="field3" pInputText formControlName="field3">
</div>
<div class="p-col-3">
<label for="field4">Field 4</label><br/>
<input id="field4" pInputText formControlName="field4">
</div>
</div>
</form>
</p-panel>
right2.component.html (Variant 2)
<p-panel [header]="'Right 2'">
<form [formGroup]="form" class="container">
<div class="p-grid">
<div class="p-col-12">
<label for="id">ID</label>
<div>
<input pInputText id="id" formControlName="id1">
<input pInputText formControlName="id2">
<input pInputText formControlName="id3">
</div>
</div>
</div>
<h3>Grouped Information</h3>
<div class="p-grid">
<div class="p-col-12">
<label for="auto">Autocomplete</label>
<p-autoComplete
id="auto"
formControlName="auto"
[suggestions]="items"
[style]="{width: '100%'}">
</p-autoComplete>
</div>
</div>
<div class="p-grid">
<div class="p-col-8">
<div class="p-grid">
<label class="p-col-12" for="description">Description</label>
<input class="p-col-12" id="description" pInputText formControlName="description">
</div>
</div>
<div class="p-col-4">
<div class="p-grid">
<label class="p-col-12" for="numeric">Numeric</label>
<input class="p-col-12" id="numeric" pInputText formControlName="numeric">
</div>
</div>
</div>
<h3>More grouped information</h3>
<div class="p-grid">
<div class="p-col-3">
<div class="p-grid">
<label class="p-col-12" for="field1">Field 1</label>
<input class="p-col-12" id="field1" pInputText formControlName="field1">
</div>
</div>
<div class="p-col-3">
<div class="p-grid">
<label class="p-col-12" for="field2">Field 2</label>
<input class="p-col-12" id="field2" pInputText formControlName="field2">
</div>
</div>
<div class="p-col-3">
<div class="p-grid">
<label class="p-col-12" for="field3">Field 3</label>
<input class="p-col-12" id="field3" pInputText formControlName="field3">
</div>
</div>
<div class="p-col-3">
<div class="p-grid">
<label class="p-col-12" for="field4">Field 4</label>
<input class="p-col-12" id="field4" pInputText formControlName="field4">
</div>
</div>
</div>
</form>
</p-panel>
right3.component.html (Variant 3)
<p-panel [header]="'Right 3'">
<form [formGroup]="form" class="container">
<div class="p-grid">
<div class="p-col-12">
<label for="id">ID</label>
<div>
<input pInputText id="id" formControlName="id1">
<input pInputText formControlName="id2">
<input pInputText formControlName="id3">
</div>
</div>
</div>
<h3>Grouped Information</h3>
<div class="p-grid">
<div class="p-col-12">
<label for="auto">Autocomplete</label>
<p-autoComplete
id="auto"
formControlName="auto"
[suggestions]="items"
[style]="{width: '100%'}">
</p-autoComplete>
</div>
</div>
<div class="p-grid">
<div class="p-col-8">
<label class="p-col-12" for="description">Description</label>
<input class="p-col-12" id="description" pInputText formControlName="description">
</div>
<div class="p-col-4">
<label class="p-col-12" for="numeric">Numeric</label>
<input class="p-col-12" id="numeric" pInputText formControlName="numeric">
</div>
</div>
<h3>More grouped information</h3>
<div class="p-grid">
<div class="p-col-3">
<label class="p-col-12" for="field1">Field 1</label>
<input class="p-col-12" id="field1" pInputText formControlName="field1">
</div>
<div class="p-col-3">
<label class="p-col-12" for="field2">Field 2</label>
<input class="p-col-12" id="field2" pInputText formControlName="field2">
</div>
<div class="p-col-3">
<label class="p-col-12" for="field3">Field 3</label>
<input class="p-col-12" id="field3" pInputText formControlName="field3">
</div>
<div class="p-col-3">
<label class="p-col-12" for="field4">Field 4</label>
<input class="p-col-12" id="field4" pInputText formControlName="field4">
</div>
</div>
</form>
</p-panel>
Screenshots illustrating the issue
Variant 1 (not growing/shrinking)
Variant 2 (growing/shrinking but missing margins)
Variant 3 (working but invalid nesting)
Add
style="width: 100%;"
To your inputs in right1.component.html (or define/use a class with width of 100%), for example:
<input id="description" style="width: 100%;" pInputText formControlName="description">
An input by default is size=20, and is not going to take up the width of the div. The p-col div is growing appropriately, just not the input inside it.