My project have follow reactive form:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div class="line">
<input class="title" id="title" placeholder="Заголовок вопроса" type="text" formControlName="title">
</div>
<div class="line">
<textarea class="question" name="question" id="question" placeholder="Текст вопроса" formControlName="question" cols="30" rows="10"></textarea>
</div>
<div class="line">
<div class="tags">
<span class="title">Метки</span>
<span class="tag" *ngFor="let tag of tags">{{ tag }} <span class="delete" (click)="deleteTag(tag)">X</span></span>
</div>
<input class="tag" id="tag" placeholder="Введите тег и нажмите enter" type="text" formControlName="tag" #tag (keyup.enter)="addTag($event, tag.value)">
</div>
<div class="line">
<button class="btn btn-common" type="submit" mat-button [disabled]="form.invalid">
Отправить
</button>
</div>
</form>
This form initialized in component:
private form: FormGroup;
ngOnInit() {
this.form = new FormGroup({
'title': new FormControl('', [Validators.required, Validators.minLength(1)]),
'question': new FormControl('', [Validators.required, Validators.minLength(3)]),
'tag': new FormControl()
});
}
In field #tag user write tagname and press Enter key. And form is submit. But i need cancel form submit after press Enter key.
my attempt:
private addTag(event, tag): void {
console.log(event);
event.preventDefault();
event.stopPropagation();
if(!tag.trim().length) { return; }
this.form.patchValue({tag: ''});
if(this.tags.indexOf(tag) === -1) {
this.tags.push(tag.trim());
}
}
But this does not stop submiting the form. I need cancel submit form after press Enter key
keyup event is too late to catch submit.
I would handle keydown event:
html
(keydown.enter)="addTag($event, tag.value)"
ts
private addTag(event, tag): void {
event.preventDefault();
}
or you can return false
html
(keydown.enter)="!!addTag(tag.value)"
^^^^
convert to boolean
ts
addTag(tag): void {
if(!tag.trim().length) { return; }
this.form.patchValue({tag: ''});
if(this.tags.indexOf(tag) === -1) {
this.tags.push(tag.trim());
}
}
Example
Related
I have an http request that pulls that data and I am populating this data on the UI. Now when the user clicks edit a form will show . How do we assign and show the value on the fields when the edit button was clicked ? cause I wanna use that data to submit. The email , firstname etc should display on the field.
When I click edit the value of the form field should be the value from the getuserdetails like firstname , lastname etc like the sample below {{this.data.emailAddress}} but instead I want it to be value of the input field
#init
ngOnInit(): void {
this._activatedRoute.queryParams.subscribe((params) => {
this.userId = params.id;
this.getUserGeneralDetails();
});
}
#constructor
constructor(
private _activatedRoute: ActivatedRoute,
private _notificationService: NotificationService,
private _userProfileService: UserProfileService,
private _router: Router,
private fb: FormBuilder
) {
this.generalForm.disable();
this.securityForm.disable();
}
I only wanna show the data on the formfield when Edit is clicked.
generalForm = new FormGroup({
email: new FormControl(),
fname: new FormControl(),
lname: new FormControl(),
phone: new FormControl(),
companyName: new FormControl(),
title: new FormControl(),
});
Just new to angular guys badly wanted to know techniques and ideas. Thank you.
#template
<div class="card" #generalCard>
<span class="anchor" id="general"></span>
<div class="card-header">
<mat-icon class="card-icon">group</mat-icon>
<div class="title">GENERAL</div>
<div class="spacer"></div>
<button mat-button *ngIf="generalForm.disabled" (click)="generalForm.enable()">
<mat-icon>edit</mat-icon> Edit
</button>
<button mat-button *ngIf="generalForm.enabled" (click)="generalForm.disable()">
Cancel
</button>
<button mat-stroked-button *ngIf="generalForm.enabled" (click)="saveGeneralFormChanges()">
Save Changes
</button>
</div>
<div class="card-content" *ngIf="generalForm.disabled" >
<div class="line-item">
<div class="title">EMAIL</div>
<div class="detail">{{this.data.emailAddress}}</div>
<mat-icon class="active" style="color:#00B0DB;">check_circle</mat-icon>
</div>
<div class="line-item">
<div class="title">EMAIL</div>
<div class="detail">{{this.data.emailAddress}}</div>
<mat-icon>check_circle_outline</mat-icon>
<button mat-button class="detail active">Resend welcome email</button>
</div>
<div class="line-item">
<div class="title">FIRST NAME</div>
<div class="detail">{{this.data.firstName}}</div>
</div>
<div class="line-item">
<div class="title">LAST NAME</div>
<div class="detail">{{this.data.lastName}}</div>
</div>
<div class="line-item">
<div class="title">PHONE NUMBER</div>
<div class="detail">+1 {{this.data.phoneNumber}}</div>
</div>
<div class="line-item">
<div class="title">COMPANY NAME</div>
<div class="detail">{{this.data.companyName || 'None'}}</div>
</div>
<div class="line-item">
<div class="title">TITLE</div>
<div class="detail">{{this.data.title || 'None'}}</div>
</div>
</div>
#GetUserData
getUserGeneralDetails() {
this.isInProgress = true;
this._userProfileService
.getUserGeneralDetails(this.userId)
.pipe(finalize(() => (this.isInProgress = false)))
.subscribe({
next: (res) => {
if (res.isSuccess) {
this.data = res.data;
}
},
error: (err) => this._notificationService.showError(err),
complete: noop,
});
}
#field code
<div class="card-content" *ngIf="generalForm.enabled">
<form [formGroup]="generalForm" class="generalForm">
<mat-form-field appearance="fill" class="email">
<mat-label>Email</mat-label>
<input matInput formControlName="email" />
</mat-form-field>
<button mat-raised-button class="validateEmail">Validate email</button>
<mat-divider></mat-divider>
<mat-form-field appearance="fill" class="fname">
<mat-label>First Name</mat-label>
<input matInput formControlName="fname" />
</mat-form-field>
<mat-form-field appearance="fill" class="lname">
<mat-label>Last Name</mat-label>
<input matInput formControlName="lname" />
</mat-form-field>
<mat-form-field appearance="fill" class="phone">
<mat-label>Phone Number</mat-label>
<input matInput formControlName="phone" />
</mat-form-field>
<mat-form-field appearance="fill" class="companyName">
<mat-label>Company Name</mat-label>
<input matInput formControlName="companyName" />
</mat-form-field>
<mat-form-field appearance="fill" class="title">
<mat-label>Title</mat-label>
<input matInput formControlName="title" />
</mat-form-field>
</form>
</div>
</div>
Your HTML code looks like good and as per ur question you are facing issue in filling data into form controls. That can be done as follow:
constructor(private fb: FormBuilder) { }
fillUpData() {
this.generalForm = this.fb.group({
email: [this.data.email, [Validators.required]],
fname: [this.data.fname, [Validators.required]],
lname: [this.data.lname, [Validators.required]],
phone: this.data.phone,
companyName: this.data.companyName,
title: this.data.title
});
}
You need to call this method once you have data. So after your API call.
getUserGeneralDetails() {
this.isInProgress = true;
this._userProfileService
.getUserGeneralDetails(this.userId)
.pipe(finalize(() => (this.isInProgress = false)))
.subscribe({
next: (res) => {
if (res.isSuccess) {
this.data = res.data; // After this call function.
this.fillUpData();
}
},
error: (err) => this._notificationService.showError(err),
complete: noop,
});
}
After doing this if you get an error related to the form group then add condition like *ngIf="generalForm" in your HTML code... That means if form exist then render its formControl...
I have been working with Vue for 24 hours now, so forgive the ignorance. I have searched around and I'm getting close, but I'm sure it's my lack of understanding and basic principles.
I have a modal that opens when a button is clicked. This modal displays a form with an email input. I managed to get the modal working, but nothing happens when I type in an incorrect email.
Here's my code for the component:
<template>
<div>
<!-- Aside -->
<aside class="aside">
<button class="aside__btn button" #click="showModal = true">
Send Me The Tips
</button>
</aside>
<!-- Modal -->
<div class="modal" v-if="showModal">
<div class="modal-container">
<p class="modal__steps">Step 1 of 2</p>
<div class="relative">
<hr class="modal__divider" />
</div>
<div class="modal__heading-container">
<p class="modal__heading">Email Your Eail To Get <span class="modal__heading-span">Free</span>
</p>
<p class="modal__heading">iPhone Photography Email Tips:</p>
</div>
<form>
<input for="email" type="email" placeholder="Please enter your email here" required v-model="email">
<span class="floating-placeholder" v-if="msg.email">{{msg.email}}</span>
<!-- <span class="floating-placeholder">Please enter your email here</span> -->
<button class="modal__button button">Send Me The Tips</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default ({
data () {
return {
showModal: false,
email: '',
msg: [],
}
},
watch: {
email(value) {
// binding this to the data value in the email input
this.email = value;
this.validateEmail(value);
}
},
methods: {
validateEmail(value){
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value))
{
this.msg['email'] = '';
} else{
this.msg['email'] = 'Please enter a valid email address';
}
}
}
})
</script>
I'm using Laravel if that's of importance.
I would delete the watch and add an event listener on blur like so:
<input for="email" type="email" placeholder="Please enter your email here" required v-model="email" #blur="validateEmail" >
and update the validateEmail method like so :
validateEmail() {
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(this.email)) {
this.msg['email'] = 'Please enter a valid email address';
} else {
this.msg['email'] = '';
}
}
You could also change the event listener to change #change if it serves your needs better.
You could also checkout Vuelidate which handles form validation. For example:
<template>
<div>
<input
class="rounded shadow-sm border border-warning"
v-model="form.email"
placeholder="E-mail"
#input="$v.form.email.$touch"
:state="$v.form.email.$dirty ? !$v.form.email.$error : null" />
</div>
</template>
<script>
import {required, email} from "vuelidate/lib/validators";
export default {
data() {
return {
form: {
email: null,
}
};
},
validations: {
form: {
email: {
required,
email
}
}
},
};
</script>
I am using Laravel-5.8 for my project. I want to upload image, and click on submit button to save the image and other text fields into the database.
Controller
public function create()
{
$countries = ConfigCountries::all();
return view('organization.companies.create')->with('countries', $countries);
}
public function store(Request $request)
{
try {
$orgStartDate = Carbon::parse($request->org_start_date);
$arr = [
'organisation_code' => $request->organisation_code,
'organisation_name' => $request->organisation_name,
'website' => $request->website,
'org_decription' => $request->org_description,
'total_employees' => $request->total_employees,
'registration_number' => $request->registration_number,
'org_start_date' => $request->$orgStartDate,
'phone_number' => $request->phone_number,
'secondary_phone' => $request->secondary_phone,
'email' => $request->email,
'secondary_email' => $request->secondary_email,
'address1' => $request->address1,
'address2' => $request->address2,
'country_id' => $request->country_id,
'created_by' => Auth::user()->id,
'created_at' => date("Y-m-d H:i:s"),
'is_active' => 1,
];
if ($request->org_image != "") {
$org_image = time() . '_' . $request->org_image->getClientOriginalName();
$request->org_image->move('storage_files/companies/profile/', $org_image);
$arr['org_image'] = 'storage_files/companies/profile/' . $org_image;
}
$company = OrgCompany::create($arr);
$company->save();
Session::flash('success', 'Company is created successfully');
return redirect()->route('organization.companies.index');
} catch (Exception $exception) {
return back()->withInput()
->withErrors(['unexpected_error' => 'Unexpected error occurred while trying to process your request.']);
}
}
view
<div class="card-body">
<form action="{{ route("organization.companies.store") }}" method="post class="form-horizontal" enctype="multipart/form-data">
{{csrf_field()}}
<div class="text-center">
<input type="image" class="profile-user-img img-fluid img-circle"
src="{{asset('theme/adminlte3/dist/img/company_logo.png')}}"
id="wizardPicturePreview" title="" width="150">
<input type="file" name="picture" id="wizard-picture" class="" hidden>
<h4 class="profile-username text-center">Click On Image to Add Logo</h4>
</div>
<span style="color:blue;"><h4 class="box-title"><b>Contact Information</b></h4></span>
<hr class="m-t-0 m-b-40">
<div class="row">
<div class="col-md-6">
<div class="form-group row">
<label class="control-label text-right col-md-3"> Phone No.</label>
<div class="col-md-9 controls">
<input type="text" name="phone_number" placeholder="Enter Company Phone no. here" class="form-control" value="{{old('phone_number')}}">
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group row">
<label class="control-label text-right col-md-3"> Alternative Phone No.</label>
<div class="col-md-9 controls">
<input type="text" name="secondary_phone" placeholder="Enter Alternative Phone no. here" class="form-control" value="{{old('secondary_phone')}}">
</div>
</div>
</div>
<!--/span-->
</div>
<hr>
<div class="form-actions">
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-offset-3 col-md-9">
<button type="submit" class="btn btn-primary">Add Company</button>
<button type="button" onclick="window.location.href='{{route('organization.companies.index')}}'" class="btn btn-default">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function(){
$("#wizard-picture").change(function(){
readURL(this);
});
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#wizardPicturePreview').attr('src', e.target.result).fadeIn('slow');
}
reader.readAsDataURL(input.files[0]);
} }
$("input[type='image']").click(function() {
$("input[id='wizard-picture']").click();
});
$(".form-control").keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
return false;
}
});
</script>
The issue is that without clicking on the save submit button, when I clicked on image file uploader, it redirects to the index page without uploading the image to the screen.
How do I resolve this?
Thanks
An input type of image is a way to define an image as a submit button, so clicking on the image actually is submitting the form. You can either change the image to a regular <img> tag or change you click handler to prevent the default action like so
$("input[type='image']").click(function(e) {
e.preventDefault();
$("input[id='wizard-picture']").click();
});
Also just a heads up, you have a typo in the line that opens your form. There's no closing quotes after method="POST which is probably why the page is just redirecting on submit
Maybe because the closing quote of method is missing in <form> starting tag
I'm trying to add textfield dynamically with angular 2 and it works as expected,but couldn't managed to get this json object :
exemple of json object which i want to get when i clic the submit button :
{fullname:"toto",etapes:[{etape:"sometext"},{etape:"sometext"}]}
heres the HTML CODE:
<form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm)">
<div style="padding:15px" class="container" style="width: 1027px !important;">
<div class="itineraire">
<div class="panel panel-default" style="width:100%">
<div class="panel-heading panelcolor"><span style="font-size: 15px;font-weight: bold">Itinéraire</span></div>
<div class="panel-body panelcolor">
<input type="text" formControlName="fullname" class="form-control" placeholder="fullename"
name="Location" >
<div formArrayName="myArray">
<div *ngFor="let myGroup of myForm.controls.myArray.controls; let i=index">
<div [formGroupName]="i">
<span *ngIf="myForm.controls.myArray.controls.length > 1" (click)="removeDataKey(i)" class="glyphicon glyphicon-remove pull-right"
style="z-index:33;cursor: pointer">
</span>
<!--[formGroupName]="myGroupName[i]"-->
<div [formGroupName]="myGroupName[i]">
<div class="inner-addon left-addon ">
<i class="glyphicon marker" style="border: 5px solid #FED141"></i>
<input type="text" style="width:50% !important" formControlName="etape" class="form-control" placeholder="Exemple : Maarif, Grand Casablanca"
name="Location" (setAddress)="getAddressOnChange($event,LocationCtrl)"><br/>
</div>
</div>
<!--[formGroupName]="myGroupName[i]"-->
</div>
<!--[formGroupName]="i" -->
</div>
</div>
<br/>
<a (click)="addArray()" style="cursor: pointer">+ Ajouter une ville étape</a>
<input type="text" style="width:30%" #newName id="newName" [hidden]="true">
</div>
</div>
<button type="submit" (click)="save()">save</button>
</form>
Component.ts :
initArray(nameObj:any) {
return this._fb.group({
[nameObj]: this._fb.group({
etape: [''],
gmtDate:[''],
})
});
}
addArray(newName:string) {
const control = <FormArray>this.myForm.controls['myArray'];
this.myGroupName.push(newName);
control.push(this.initArray(newName));
}
ngOnInit() {
this.myForm = this._fb.group({
myArray: this._fb.array([
this._fb.group({
test: this._fb.group({
etape: [''],
gmtDate:['']
})
}),
])
});
}
save(){
console.log(myObject);
}
so, what are the changes that i have to do in my code to get the like the Json object above, when i click the submit button, please help i got stuck on this.
If you want:
{fullname:"toto",etapes:[{etape:"sometext"},{etape:"sometext"}]}
your form should looks like: (we dont need the formGroupName )
this.myForm = this._fb.group({
fullname: ['', Validators.required ],
etapes: this._fb.array([
this._fb.group({
etape: ['']
},
this._fb.group({
etape: ['']
},
...
)
])
});
So, to have it dynamically, your initArray()should be like:
initArray() {
return this._fb.group({
etape: ['']
});
}
and adding an array should looks like:
addArray(newName:string) {
const control = <FormArray>this.myForm.controls['etapes']
control.push(this.initArray());
}
NB: You dont need the (click)="save()" anymore in the submit button, since you already call it when submit.
a working plunker: http://plnkr.co/edit/Nq4jrC5g0tfxE0NCTfoQ?p=preview
HI can you try like this
save(){
console.log(this.myForm.value);
}
#imsi imsi
you have
<div [formGroupName]="myGroupName[i]"> //WRONG
<div [formGroupName]="myGroup[i]"> //<--it's myGroup
I have a form in Angular 2 which I'm validating by the model-driven way. I wanna know how do I change the status from false to true, because I have the rules of validation and even if the user fills everything right, it keeps returning me invalid (false). Here's the HTML code.
<div class="wrap-page">
<form [formGroup]="myForm" novalidate class="form-contato" (ngSubmit)="enviarMensagem(myForm.value, myForm.valid)">
<div class=row>
<div class="col s12">
<h4> Contato </h4>
</div>
<div class="col s12 m12 l6">
<label> Nome: </label>
<input type="text" name="nome" formControlName="nome" class="forms-econ" required placeholder="ex: José Silva">
<div class="div-validar">
<span [hidden]="myForm.controls.nome.valid || (myForm.controls.nome.pristine && !submitted)">
Nome Inválido (mínimo 3 caracteres).
</span>
</div>
</div>
<div class="col s12 l6">
<label> E-mail: </label>
<input type="email" class="forms-econ" formControlName="email" required name="email" pattern="^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$"
placeholder="exemplo#exemplo.com">
<div class="div-validar">
<span [hidden]="myForm.controls.email.valid || (myForm.controls.email.pristine && !submitted)">
E-Mail inválido
</span>
</div>
</div>
<div class="col s12 l6">
<label>Telefone: </label>
<input type="tel" class="forms-econ" name="telefone" formControlName="telefone" pattern="[0-9]" placeholder="(xx)9 9999-99999">
</div>
<div class="col s12 l6">
<label> Motivo do Contato: </label>
<select name="assunto" formControlName="assunto" class="forms-econ">
<option value="motivo_01">Motivo 01</option>
<option value="motivo_02">Motivo 02</option>
<option value="motivo_03">Motivo 03</option>
<option value="motivo_03">Motivo 04</option>
</select>
</div>
<div class="col s12">
<label> Mensagem: </label>
<textarea name="mensagem" formControlName="mensagem" placeholder="Mensagem..." rows="15">
</textarea>
<div class="div-validar">
<span [hidden]="myForm.controls.mensagem.valid || (myForm.controls.mensagem.pristine && !submitted)">
O campo mensagem é obrigatório
</span>
</div>
</div>
<div class="col s12">
<label> ID: </label>
<textarea name="id" formControlName="id" placeholder="Mensagem..." rows="15">
</textarea>
</div>
<h1> {{myForm.valid | json}} </h1> // <-- Here is where I'm printing the status of the form (always return false)
<div class="col s12 right-align">
<input type="submit" value="Enviar" class="btn-form">
</div>
</div>
</form>
</div>
And here is the component.
import { Component, Input } from '#angular/core';
import {FormGroup, FormControl, FormBuilder, Validators} from '#angular/forms';
import {formContato} from './contato.interface';
import {ContatoService} from './contato.service';
#Component({
moduleId: module.id,
selector: 'contato',
templateUrl: `contato.component.html`,
providers: [ContatoService]
})
export class ContatoComponent {
public contato:formContato;
public myForm: FormGroup;
public submitted: boolean;
public events: any[] = [];
constructor(private _fb: FormBuilder, private mensagemContato:ContatoService) { }
ngOnInit() {
this.myForm = this._fb.group({
nome: ['', [<any>Validators.required, <any>Validators.minLength(3)]],
email: ['', <any>Validators.required],
telefone: ['', <any>Validators.required],
assunto: ['', <any>Validators.required],
mensagem: ['', <any>Validators.required],
id: ['']
})
}
enviarMensagem(model: formContato, isValid: boolean) {
this.submitted = true;
console.log(model, isValid); // -< another way to print the status of the form (always false)
}
}
Thanks in advance :)
Your problem is with the e-mail and phone validation. They always validate as false.
Since you are using a reactive form, I would suggest you move your pattern checks to your build of the form, e.g:
email: ['', [<any>Validators.required, Validators.pattern(....)]],
Then I would assume that you want to inform right from the beginning that fields are required. This can be done in quite a few ways, here I show two possible solutions:
<span *ngIf="myForm.get('nome').hasError('required')">
Name required!
</span><br>
or:
<span *ngIf="!myForm.controls.nome.pristine">
Name required!
</span><br>
and as mentioned in other answer, you need not to pass the myForm.valid in the submit.
I made a Plunker for you, where I set another e-mail validation:
EMAIL_REGEXP = '^[a-z0-9]+(\.[_a-z0-9]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,15})$';
and just a random phone number validation, since I wasn't sure exactly what kind of number validation you need. This one checks that the phone number only contains numbers.
If you want you could also disable the submit button if the form is not valid:
<input [disabled]="!myForm.valid" type="submit" value="Enviar" class="btn-form">
but that is of course up to you! :)
Hope this helps!
In Angular 2 , its not required to pass the valid entity on (ngSubmit) , just pass the required form name give to the form group directive .
(ngSubmit)="enviarMensagem(myForm)"
enviarMensagem({model, valid }: {model: Object, valid: boolean}) {
this.submitted = true;
console.log(model, valid);
}