Hi i have a question about Angular 2 and really don't know how to do that and I need your help :)
I have a child component that have a simple registration form but the submit button on parent template. So when I press the submit button it will get data from child component form.
here is my example.
Parent component ts
import {Component, ViewChild, OnDestroy, Output, EventEmitter} from '#angular/core';
import {GlobalEvent} from 'app/shared/GlobalEvent';
#Component({
selector: 'signup',
templateUrl: 'SignUpModalComponent.html',
styleUrls: ['SignUpModalComponent.scss'],
})
export class SignUpModalComponent implements OnDestroy {
public overlayState: boolean;
public step: number = 1;
public formSubmit: boolean;
#ViewChild('firstModal')
modal: any;
constructor(private modalEventService: GlobalEvent) {
this.modalEventService.modalChangeEvent.subscribe((res: boolean) => {
this.overlayState = res;
if (res) {
this.modal.open();
} else {
this.modal.close();
}
});
}
closeModal(value: boolean): void {
this.modalEventService.close(false);
this.modal.close()
}
ngOnDestroy() {
this.modalEventService.modalChangeEvent.unsubscribe();
}
incrementStep():void {
this.step += 1;
}
decrementStep():void {
this.step -= 1;
}
onFormSubmit(): void {
this.formSubmit = true;
}
}
Parent component html template
<div class="modal-overlay" *ngIf="overlayState"></div>
<modal (onClose)="closeModal(false)" #firstModal >
<modal-header>
<button (click)="firstModal.close()" class="close-btn"><i class="material-icons">close</i></button>
<div class="steps-container">
<span [ngClass]="{'active': step == 1 }">1</span>
<span [ngClass]="{'active': step == 2 }">2</span>
<span [ngClass]="{'active': step == 3 }">3</span>
<span [ngClass]="{'active': step == 4 }">4</span>
</div>
</modal-header>
<modal-content>
<signup-form [hidden]="step != 1" [formSubmit]="formSubmit"></signup-form>
<signup-social ngClass="social-step{{step}}" [step]="step"></signup-social>
</modal-content>
<modal-footer>
<button md-button (click)="decrementStep()" [hidden]="step == 1"><Back</button>
<button md-button (click)="incrementStep(); onFormSubmit()" [hidden]="step != 1">Next></button>
<button md-button (click)="incrementStep()" [hidden]="step == 1 || step == 4">Skip</button>
</modal-footer>
</modal>
Child component ts file
import {Component, OnInit, Input} from '#angular/core';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
import {CustomValidators} from 'ng2-validation';
import {SignUpFormInterface} from './SignUpFormInterface';
#Component({
selector: 'signup-form',
templateUrl: 'SignUpForm.html',
styleUrls: ['SignUpForm.scss']
})
export class SignUpForm implements OnInit {
signupInfo: FormGroup;
public tmppass: any;
#Input() set formSubmit(sendData: boolean) {
if (sendData) {
}
}
constructor(private formbuilder: FormBuilder) {
}
ngOnInit() {
this.signupInfo = this.formbuilder.group({
email: ['', [CustomValidators.email]],
username: ['', [Validators.required, CustomValidators.min(10)]],
password: ['', [Validators.required, CustomValidators.rangeLength([5, 100]), this.setPass]],
confirmPassword: ['', [Validators.required, CustomValidators.rangeLength([5, 100]), CustomValidators.equal(this.tmppass)]],
fullName: ['', [Validators.required, CustomValidators.min(10)]],
gender: ['', [Validators.required]],
countrys: ['', [Validators.required]],
});
}
setPass(c: any): void {
console.log('sdsd', c.value);
if (c.value) {
this.tmppass = '';
this.tmppass = <string>c.value;
}
}
onSubmit({value, valid}: {value: SignUpFormInterface, valid: boolean}) {
console.log(this.signupInfo);
}
cons() {
console.log(this.signupInfo);
}
}
function validateEmail(c: any) {
let EMAIL_REGEXP = /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
return EMAIL_REGEXP.test(c.value) ? c.email = false : c.email = true;
}
Child component html template
<div class="sign-up-form clearfix">
<form novalidate (ngSubmit)="onSubmit(signupInfo)" [formGroup]="signupInfo">
<label>
<input type="file" placeholder="Last Name*" name="lastName"/>
upload an avatar
</label>
<md-input-container>
<input md-input placeholder="Email address*" name="email" formControlName="email"/>
</md-input-container>
<!--<p *ngIf="signupInfo.controls.email.errors?.email">error message</p>-->
<div class="errror-msg" *ngIf="signupInfo.controls.email.errors?.email">
<md-hint>
<span>Name should be minimum 6 characters</span>
</md-hint>
</div>
<p *ngIf="signupInfo.controls.username.errors?.min">error message</p>
<div class="input-wrap" [ngClass]="{'error': signupInfo.controls.username.errors?.min}">
<md-input-container>
<input md-input placeholder="Username*" name="username" formControlName="username"/>
</md-input-container>
<div class="errror-msg" *ngIf="signupInfo.controls.username.errors?.min">
<md-hint>
<span>Name should be minimum 6 characters</span>
</md-hint>
</div>
<div class="errror-msg"
*ngIf="signupInfo.get('username').hasError('minlength') && signupInfo.get('username').touched">
<md-hint>
<span>Name should be minimum 6 characters</span>
</md-hint>
</div>
</div>
<p *ngIf="signupInfo.controls.password.errors?.rangeLength">error xcdfdfd</p>
<md-input-container>
<input md-input placeholder="Password*" formControlName="password"/>
</md-input-container>
<p *ngIf="signupInfo.controls.confirmPassword.errors?.rangeLength">error password</p>
<p *ngIf="signupInfo.controls.confirmPassword.errors?.equal">error equal</p>
<md-input-container>
<input md-input placeholder="Confirm Password*" formControlName="confirmPassword"/>
</md-input-container>
<p *ngIf="signupInfo.controls.fullName.errors?.min">error password</p>
<md-input-container>
<input md-input placeholder="Full Name*" name="fullName" formControlName="fullName"/>
</md-input-container>
<p *ngIf="signupInfo.controls.gender.errors?.required">error password</p>
<md-select placeholder="Gender" formControlName="gender">
<md-option *ngFor="let food of ['react','angular']" [value]="food">
{{ food }}
</md-option>
</md-select>
<p *ngIf="signupInfo.controls.countrys.errors?.required">error password</p>
<md-select placeholder="Country" formControlName="countrys">
<md-option *ngFor="let country of countrys" [value]="country">
{{ country.name }}
</md-option>
</md-select>
<div class="input-wrap">
<md-input-container placeholder="Date of Birth *">
<input md-input placeholder="mm/dd/yyyy" type="text" name="DateofBirth"/>
</md-input-container>
</div>
</form>
</div>
Thanks for help :)
Related
When i click on any button inside a form, all functions registered inside the form would be executed.
item.components.ts
import { Component, OnInit } from '#angular/core';
import { ItemsService } from '../../share/items.service';
import { MatDialogRef } from '#angular/material';
import { Item } from 'src/app/model/item';
#Component({
selector: 'app-item',
templateUrl: './item.component.html',
styleUrls: ['./item.component.scss']
})
export class ItemComponent implements OnInit {
constructor(public service:ItemsService,
public dialogRef: MatDialogRef<ItemComponent>) { }
ngOnInit() { }
onSubmit(model: Item, isValid: boolean){
console.log('!!! submit !!!');
}
addProperty(){
console.log('!!! add prop !!!');
}
onClear(){
console.log('!!! clear !!!');
}
onClose(){
console.log('!!! close !!!');
}
}
item.ts
export interface Item {
id: BigInteger | null
artNr: string;
name: string;
parentGroup: string;
childGroup: string;
properties: Array<{key: string, text: string}>;
}
items.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse} from '#angular/common/http';
import { Observable, from } from 'rxjs';
import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, FormArray } from '#angular/forms'
import { Address } from '../model/address';
import { Item } from '../model/item';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'my-auth-token'
})
};
interface ResponseItem{
results:Item[];
}
#Injectable({
providedIn: 'root'
})
export class ItemsService {
constructor(private http:HttpClient, private formBuilder:FormBuilder) { }
ngOnInit(){
this.initializeItemFormGroup();
}
//** ITEM AREA */
itemForm: FormGroup;
initializeItemFormGroup(){
this.itemForm = this.formBuilder.group({
id: [null],
artNr: ['', [Validators.required]],
name: ['', [Validators.required]],
parentGroup: ['', [Validators.required]],
childGroup: [''],
properties: this.formBuilder.array([this.addPropertyGroup()] )
});
}
addPropertyGroup(){
return this.formBuilder.group({
key: [''],
text: ['']
})
}
removeProperty(index){
this.property.removeAt(index);
}
addProperty() {
this.property.push(this.addPropertyGroup());
}
get property():FormArray {
return <FormArray>this.itemForm.get('properties');
}
}
item.component.html
<form [formGroup]="service.itemForm" class="normal-form" (ngSubmit)="onSubmit(service.itemForm.value, service.itemForm.valid)">
<mat-grid-list cols="2">
<mat-grid-tile>
<div class="controles-container">
<input type="hidden" formControlName="id" >
<mat-form-field>
<input formControlName="artNr" matInput placeholder="EA0123" >
<mat-error>Artikelnummer zwingend erforderlich</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="name" matInput placeholder="Artikelbezeichnung" >
<mat-error>Bezeichnung ist erforderlich</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="parentGroup" matInput placeholder="Karosserie" >
</mat-form-field>
<mat-form-field>
<input formControlName="childGroup" matInput placeholder="Schrauben" >
</mat-form-field>
</div>
</mat-grid-tile>
<mat-grid-tile>
<button mat-icon-button (click)="addProperty()"><mat-icon>add</mat-icon></button>
<div class="make-scrollable" formArrayName="properties">
<div *ngFor="let property of service.itemForm.controls.properties?.value; let i=index;" class="panel panel-default">
<ng-container [formGroupName]="i">
<mat-form-field>
<input formControlName="key" matInput placeholder="Titel" >
</mat-form-field>
<mat-form-field>
<input formControlName="text" matInput placeholder="Beschreibender Text" >
</mat-form-field>
</ng-container>
</div>
</div>
</mat-grid-tile>
<mat-grid-tile [colspan]="2">
<div class="buttom-row">
<button mat-raised-button color="primary" type="submit" [disabled]="service.itemForm.invalid">Speichern</button>
<button mat-raised-button color="warn" (click)="onClear()">Bereinigen</button>
</div>
</mat-grid-tile>
</mat-grid-list>
</form>
When i click any Button, the console is logging (currently I tried to add a property: (click)="addProperty()")
Console output:
item.component.ts:32 !!! add prop !!!
item.component.ts:26 !!! submit !!!
item.component.ts:44 !!! close !!!
But i expect the following output
Console output:
item.component.ts:32 !!! add prop !!!
Thanks to Julius Dzidzevičius.
He told me to set the button type="button"
Now everything works fine!!!
See below
´´´HTML
<form [formGroup]="service.itemForm" class="normal-form" (ngSubmit)="onSubmit(service.itemForm.value, service.itemForm.valid)">
<mat-grid-list cols="2">
<mat-grid-tile>
<div class="controles-container">
<input type="hidden" formControlName="id" >
<mat-form-field>
<input formControlName="artNr" matInput placeholder="EA0123" >
<mat-error>Artikelnummer zwingend erforderlich</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="name" matInput placeholder="Artikelbezeichnung" >
<mat-error>Bezeichnung ist erforderlich</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="parentGroup" matInput placeholder="Karosserie" >
</mat-form-field>
<mat-form-field>
<input formControlName="childGroup" matInput placeholder="Schrauben" >
</mat-form-field>
</div>
</mat-grid-tile>
<mat-grid-tile>
<button mat-icon-button type="button" (click)="addProperty()"><mat-icon>add</mat-icon></button>
<div class="make-scrollable" formArrayName="properties">
<div *ngFor="let property of service.itemForm.controls.properties?.value; let i=index;" class="panel panel-default">
<ng-container [formGroupName]="i">
<mat-form-field>
<input formControlName="key" matInput placeholder="Titel" >
</mat-form-field>
<mat-form-field>
<input formControlName="text" matInput placeholder="Beschreibender Text" >
</mat-form-field>
</ng-container>
</div>
</div>
</mat-grid-tile>
<mat-grid-tile [colspan]="2">
<div class="buttom-row">
<button mat-raised-button color="primary" type="submit" [disabled]="service.itemForm.invalid">Speichern</button>
<button mat-raised-button type="button" color="warn" (click)="onClear()">Bereinigen</button>
</div>
</mat-grid-tile>
</mat-grid-list>
</form>
´´´´
I am working through the challenges for a Udemy course on Angular 4, but I am stuck on a challenge where I have to create an input for a new password and then another input to confirm the new password using reactive forms.
I have an external .ts file called password.validators.ts that has custom form validation code, and I can get the value of the currently selected input box by passing a control object with AbstractControl, but how do I pass a value to my component.ts file and then from my component.ts to my password.validators.ts ? I need to be able to compare the new password value to the confirm password value and I'm stuck!
new-password.component.html
<form [formGroup]="form">
<div class="form-group">
<label for="oldPassword">Old Password</label>
<input
formControlName="oldPassword"
id="oldPassword"
type="text"
class="form-control">
<div *ngIf="oldPassword.pending">Checking password...</div>
<div *ngIf="oldPassword.touched && oldPassword.invalid" class="alert alert-danger">
<div *ngIf="oldPassword.errors.required">Old password is required</div>
<div *ngIf="oldPassword.errors.checkOldPassword">Password is incorrect</div>
</div>
</div>
<div class="form-group">
<label for="newPassword">New password</label>
<input
formControlName="newPassword"
id="newPassword"
type="text"
class="form-control">
<div *ngIf="newPassword.touched && newPassword.invalid" class="alert alert-danger">
<div *ngIf="newPassword.errors.required">New password is required</div>
</div>
</div>
<div class="form-group">
<label for="confirmNewPassword">Confirm new password</label>
<input
formControlName="confirmNewPassword"
id="confirmNewPassword"
type="text"
class="form-control">
<div *ngIf="confirmNewPassword.touched && confirmNewPassword.invalid" class="alert alert-danger">
<div *ngIf="confirmNewPassword.errors.required">Confirm password is required</div>
<div *ngIf="confirmNewPassword.errors.confirmNewPassword">Passwords don't match</div>
</div>
</div>
<button class="btn btn-primary" type="submit">Change Password</button>
</form>
new-password.component.ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { PasswordValidators } from './password.validators';
#Component({
selector: 'new-password',
templateUrl: './new-password.component.html',
styleUrls: ['./new-password.component.css']
})
export class NewPasswordComponent {
form = new FormGroup({
oldPassword: new FormControl('', Validators.required, PasswordValidators.checkOldPassword),
newPassword: new FormControl('', Validators.required),
confirmNewPassword: new FormControl('', Validators.required )
})
get oldPassword() {
return this.form.get('oldPassword');
}
get newPassword() {
return this.form.get('newPassword');
}
get confirmNewPassword() {
return this.form.get('confirmNewPassword');
}
addNewPassword(newPassword: HTMLInputElement) {
let np = this.newPassword;
return np;
}
}
password.validators.ts
import { AbstractControl, ValidationErrors } from '#angular/forms';
export class PasswordValidators {
static checkOldPassword(control: AbstractControl) : Promise<ValidationErrors | null> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(control.value !== '1234')
resolve({ checkOldPassword: true }) ;
else resolve(null);
}, 2000);
});
}
static confirmNewPassword(control: AbstractControl) : ValidationErrors | null {
if(control.value === control.newPassword.value)
return null;
}
}
I have used the following code for my password validation may be this can help you
In password.validator write this code
import {AbstractControl} from '#angular/forms';
export class PasswordValidation {
static MatchPassword(AC: AbstractControl) {
let password = AC.get('password').value;
let confirmPassword = AC.get('confirmPassword').value;
if(password != confirmPassword) {
console.log('false');
AC.get('confirmPassword').setErrors( {MatchPassword: true} )
} else {
console.log('true');
return null
}
}
}
and in the component file use this code
constructor(fb: FormBuilder)
{
this.form = fb.group({
password: ['', Validators.required],
confirmPassword: ['', Validators.required]
}, {
validator: PasswordValidation.MatchPassword // your validation method
})
}
and in html file to find error use this code
<div class="alert alert-danger" *ngIf="form.controls.confirmPassword.errors?.MutchPassword">Password not match</div>
Hope it would help you
Looking to understand why this isn't working as intended and possible ways to fix. I run this function and try to get it to return information filled out on a registration form to later attach to my data model. I am trying on the first entry to also put in default values so they do not stay empty as I am using MongoDB to store the data. The data model can see everything but "objects".
register.component.ts
import { Component, OnInit } from '#angular/core';
import { ValidateService } from '../../services/validate.service';
import { FlashMessagesService } from 'angular2-flash-messages';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent{
name: String;
email: String;
phonenumber: String;
username: String;
password: String;
objects: Object;
object1: Object;
object2: Object;
foo: String;
bar: String;
constructor(private validateService: ValidateService,
private flashMessage: FlashMessagesService,
private authService: AuthService,
private router: Router) { }
onRegisterSubmit(){
const user = {
name: this.name,
email: this.email,
phonenumber: this.phonenumber,
username: this.username,
password: this.password,
objects: {
object1: {
foo: "no foo",
bar: "no bar"
},
object2: {
foo: "no foo",
bar: "no bar"
}
}
}
this.authService.registerUser(user).subscribe(data => {
if(data.success){
this.flashMessage.show('You are now registered and can log in', {cssClass: 'alert-success', timeout: 3000});
this.router.navigate(['/login']);
} else {
this.flashMessage.show('Something went wrong', {cssClass: 'alert-danger', timeout: 3000});
this.router.navigate(['/register']);
}
});
}
register.component.html
<h2 class="page-header">Register</h2>
<form (submit)="onRegisterSubmit()">
<div class="form-group">
<label>Name</label>
<input type="text" [(ngModel)]="name" name="name" class="form-control">
</div>
<div class="form-group">
<label>Username</label>
<input type="text" [(ngModel)]="username" name="username" class="form-control">
</div>
<div class="form-group">
<label>Email</label>
<input type="text" [(ngModel)]="email" name="email" class="form-control" >
</div>
<div class="form-group">
<label>Phonenumber</label>
<input type="text" [(ngModel)]="phonenumber" name="phonenumber" class="form-control" >
</div>
<div class="form-group">
<label>Password</label>
<input type="password" [(ngModel)]="password" name="password" class="form-control">
</div>
<input type="submit" class="btn btn-primary" value="Submit">
</form>
I have a repeating Form for every CustomerProject. The repeating form shows all the Projects for a Customer. If i have for example 5 project forms, i want to edit 3 and add 2 and hit submit, posting / putting everything at once.
The question is how do i accomplish this?
Form HTML:
<form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm)">
<!--projects-->
<div formArrayName="projects">
<div *ngFor="let project of myForm.controls.projects.controls; let i=index" class="panel panel-default">
<div class="panel-heading">
<span>Project {{i + 1}}</span>
<span class="glyphicon glyphicon-remove pull-right" *ngIf="myForm.controls.projects.controls.length > 1" (click)="removeProject(i)"></span>
</div>
<div class="panel-body" [formGroupName]="i">
<div class="form-group col-xs-6">
<label>Customer</label>
<input type="text" class="form-control" formControlName="customer_id">
<small [hidden]="myForm.controls.projects.controls[i].controls.customer_id.valid" class="text-danger">
Street is required
</small>
</div>
<div class="form-group col-xs-6">
<label>Project</label>
<input type="text" class="form-control" formControlName="project">
</div>
</div>
</div>
</div>
<div class="margin-20">
<a (click)="addProject()" style="cursor: default">
Add another project +
</a>
</div>
<div class="margin-20">
<button type="submit" class="btn btn-inverse pull-right" [disabled]="!myForm.valid">Submit</button>
</div>
Typescript
public myForm: FormGroup;
private projects: CustomerProject[];
private project: CustomerProject;
private showForm: boolean = false;
#Input() customer: Customer = new Customer(1, '', '', '', '', '', '', '');
#Input() listId: string;
#Input() editId: string;
constructor(
private _fb: FormBuilder,
private authService: AuthService,
private projectService: CustomerProjectService
) { }
loadProjects() {
this.projectService.getCustomerProjects(this.customer.id)
.subscribe(projects => {
this.projects = projects;
console.log(this.project);
this.initForm();
},
err => {
console.error(err);
this.authService.tokenValid();
})
}
initForm() {
this.myForm = this._fb.group({
projects: this._fb.array([])
});
// add existing customer projects
this.addProjects();
//this.addProject('', '');
this.showForm = true;
}
ngOnInit() {
this.loadProjects();
}
ngOnChanges(changes) {
EmitterService.get(this.editId).subscribe((customer: Customer) => {
this.customer = customer;
this.loadProjects();
});
}
initProject(customer_id: string, project: string) {
return this._fb.group({
customer_id: [customer_id],
project: [project]
})
}
addProject(customer_id: string, project: string) {
const control = <FormArray>this.myForm.controls['projects'];
control.push(this.initProject(customer_id, project));
}
addProjects() {
for (var i = 0; i < this.projects.length; i++){
this.project = this.projects[i];
var customer_id = this.project.customer_id;
var project = this.project.project;
this.addProject(customer_id, project);
}
}
removeProject(i: number) {
const control = <FormArray>this.myForm.controls['projects'];
control.removeAt(i);
}
save(model: any) {
}
Its not recommended to posting forms at once.
UI: it gets too way complex. showing multiple forms makes users baffled.
UX: users expect add, edit or remove does CRUD at the moment and would not wait to press submit button.
Software Architecture: it violates separation of concern principle.
Good Morning,
I'm new to Angular and happily learning away.
I'm successfully loading form into my Modal on a "viewDetails" click.
However when I make a slight change to the Form from <form ngNoForm > to <form #editCashMovementForm="ngForm"> the data no longer loads.
I'm trying to make an editable pop-up form that updates on submit but its just this last step that I'm failing on.
Does anybody have advice please?
Thanks
Gws
Component.HTML
<div>
<table class="table table-hover">
<thead>
<tr>
<th><i class="fa fa-text-width fa-2x" aria-hidden="true"></i>Cash Movement ID</th>
<th><i class="fa fa-user fa-2x" aria-hidden="true"></i>PortfolioCode</th>
<th><i class="fa fa-paragraph fa-2x" aria-hidden="true"></i>CCY Out</th>
<th><i class="fa fa-map-marker fa-2x" aria-hidden="true"></i>Account Out</th>
<th><i class="fa fa-calendar-o fa-2x" aria-hidden="true"></i>Date</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let cashmovement of cashmovements">
<td> {{cashmovement.cashMovementId}}</td>
<td>{{cashmovement.portfolioCode}}</td>
<td>{{cashmovement.ccyo}}</td>
<td>{{cashmovement.accountO}}</td>
<td>{{cashmovement.date | dateFormat | date:'medium'}}</td>
<td><button class="btn btn-danger" (click)="removeCashMovement(cashmovement)"><i class="fa fa-trash" aria-hidden="true"></i>Delete</button></td>
<td><button class="btn btn-primary" (click)="viewCashMovementDetails(cashmovement.cashMovementId)"><i class="fa fa-info-circle" aria-hidden="true"></i>Edit</button></td>
</tr>
</tbody>
</table>
</div>
<div bsModal #childModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" *ngIf="selectedCashMovementLoaded">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hideChildModal()"><span aria-hidden="true">×</span></button>
<h4>{{cashmovementDetails.cashMovementId}} Details</h4>
</div>
<div class="modal-body">
<form ngNoForm >
<!--<form #editCashMovementForm="ngForm" (ngSubmit)="updateCashMovement(editCashMovementForm)">-->
<div class="form-group">
<div class="row">
<div class="col-md-4">
<label class="control-label"><i class="fa fa-user" aria-hidden="true"></i>Portfolio Code</label>
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.portfolioCode" />
</div>
<div class="col-md-4">
<label class="control-label"><i class="fa fa-text-width" aria-hidden="true"></i>Currency Out</label>
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.ccyo" />
</div>
<div class="col-md-4">
<label class="control-label"><i class="fa fa-paragraph" aria-hidden="true"></i>Account Out</label>
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.accountO" />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-xs-6">
<label class="control-label"><i class="fa fa-calendar-o" aria-hidden="true"></i>Date</label>
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.date" />
</div>
</div>
</div>
<hr/>
<button type="button" [disabled]="!editCashMovementForm.form.valid" class="btn btn-default" (click)="updateCashMovement(editCashMovementForm)"><i class="fa fa-pencil-square-o" aria-hidden="true"></i>Update</button>
</form>
</div>
</div>
</div>
</div>
Component.ts
import { Component, OnInit, ViewChild, Input, Output, trigger, state, style, animate, transition } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { NgForm } from '#angular/forms';
import { ModalDirective } from 'ng2-bootstrap';
import { CashMovementDataService } from './cashmovement.data.service';
import { DateFormatPipe } from '../shared/pipes/date-format.pipe';
import { ItemsService } from '../shared/utils/items.service';
import { NotificationService } from '../shared/utils/notification.service';
import { ConfigService } from '../shared/utils/config.service';
import { MappingService } from '../shared/utils/mapping.service';
import { ICashMovement, Pagination, PaginatedResult } from '../shared/interfaces';
#Component({
moduleId: module.id,
selector: 'cashmovements',
templateUrl: './cashmovement-list.component.html'
})
export class CashMovementListComponent implements OnInit {
#ViewChild('childModal') public childModal: ModalDirective;
cashmovements: ICashMovement[];
// Modal properties
#ViewChild('modal')
modal: any;
items: string[] = ['item1', 'item2', 'item3'];
selected: string;
output: string;
selectedCashMovementId: number;
cashmovementDetails: ICashMovement;
selectedCashMovementLoaded: boolean = false;
index: number = 0;
backdropOptions = [true, false, 'static'];
animation: boolean = true;
keyboard: boolean = true;
backdrop: string | boolean = true;
constructor(private route: ActivatedRoute,
private router: Router,
private dataService: CashMovementDataService,
private itemsService: ItemsService,
private notificationService: NotificationService,
private configService: ConfigService,
private mappingService: MappingService) { }
ngOnInit() {
this.loadCashMovements();
}
loadCashMovements(){
this.dataService.getCashMovements()
.subscribe((cashmovements: ICashMovement[]) => {
this.cashmovements = cashmovements;
},
error => {
this.notificationService.printErrorMessage('Failed to load cashmovements. ' + error);
});
}
removeCashMovement(cashmovement: ICashMovement) {
this.notificationService.openConfirmationDialog('Are you sure you want to delete this cashmovement?',
() => {
this.dataService.deleteCashMovement(cashmovement.cashMovementId)
.subscribe(() => {
this.itemsService.removeItemFromArray<ICashMovement>(this.cashmovements, cashmovement);
this.notificationService.printSuccessMessage(cashmovement.cashMovementId + ' has been deleted.');
},
error => {
this.notificationService.printErrorMessage('Failed to delete ' + cashmovement.cashMovementId + ' ' + error);
});
});
}
viewCashMovementDetails(id: number) {
this.selectedCashMovementId = id;
this.dataService.getCashMovement(this.selectedCashMovementId)
.subscribe((cashmovement: ICashMovement) => {
this.cashmovementDetails = this.itemsService.getSerialized<ICashMovement>(cashmovement);
this.cashmovementDetails.date = new DateFormatPipe().transform(cashmovement.date, ['local']);
this.selectedCashMovementLoaded = true;
this.childModal.show();
},
error => {
this.notificationService.printErrorMessage('Failed to load cashmovement. ' + error);
});
}
updateCashMovement(editCashMovementForm: NgForm) {
var scheduleMapped = this.mappingService.mapCashMovementDetailsToCashMovement(this.cashmovementDetails);
this.dataService.updateCashMovement(scheduleMapped)
.subscribe(() => {
this.notificationService.printSuccessMessage('Cash Movement has been updated');
},
error => {
this.notificationService.printErrorMessage('Failed to update cash movement. ' + error);
});
}
public hideChildModal(): void {
this.childModal.hide();
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { ICashMovement, ICashMovementDetails, Pagination, PaginatedResult } from '../shared/interfaces';
import { ItemsService } from '../shared/utils/items.service';
import { ConfigService } from '../shared/utils/config.service';
#Injectable()
export class CashMovementDataService {
_baseUrl: string = '';
constructor(private http: Http,
private itemsService: ItemsService,
private configService: ConfigService) {
this._baseUrl = configService.getApiURI();
}
getCashMovements(): Observable<void> {
return this.http.get(this._baseUrl + 'cashmovements')
.map((res: Response) => { return res.json(); })
.catch(this.handleError);
}
deleteCashMovement(id: number): Observable<void> {
return this.http.delete(this._baseUrl + 'cashmovements/?id=' + id)
.map((res: Response) => {
return;
})
.catch(this.handleError);
}
getCashMovement(id: number): Observable<ICashMovement> {
return this.http.get(this._baseUrl + 'cashmovements/?id=' + id)
.map((res: Response) => {
return res.json();
})
.catch(this.handleError);
}
updateCashMovement(cashmovement: ICashMovement): Observable<void> {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.put(this._baseUrl + 'cashmovements/?id=' + cashmovement.cashMovementId, JSON.stringify(cashmovement), {
headers: headers
})
.map((res: Response) => {
return;
})
.catch(this.handleError);
}
private handleError(error: any) {
var applicationError = error.headers.get('Application-Error');
var serverError = error.json();
var modelStateErrors: string = '';
if (!serverError.type) {
console.log(serverError);
for (var key in serverError) {
if (serverError[key])
modelStateErrors += serverError[key] + '\n';
}
}
modelStateErrors = modelStateErrors = '' ? null : modelStateErrors;
return Observable.throw(applicationError || modelStateErrors || 'Server error');
}
}
I need to change my form inputs from
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.portfolioCode" />
To
<input type="text" class="form-control" [(ngModel)]="cashmovementDetails.portfolioCode" name="portfolioCode" #portfolioCode="ngModel"/>