I am trying to test a form in Vue, using the forms from the Bootstrap-Vue library.
I have made a an event for the form (submit) and I added a function to this event (addText).
Then I made a method for this function, telling it to log my input data to the console, but when I press the "save" button and go into the console nothing has been logged.
This used to work with Materialize, so I am wondering if the error lies somewhere with the Bootstrap forms.
Any help will be much appreciated.
<template>
<b-container fluid>
<h2>Add or edit content for this section</h2>
<b-form-group #submit="addText">
<div class="fieldHeadline">
<label for="headline">Add headline</label>
<b-form-input type="text" name="headline" v-model="headline"></b-form-input>
</div>
<div class="fieldSecodnaryHeadline">
<label for="secondaryHeadline">Add secondary headline</label>
<b-form-input type="text" name="secondaryHeadline" v-model="secondaryHeadline"></b-form-input>
</div>
<div class="fieldText">
<label for="text">add text</label>
<b-form-input type="text" name="text" v-model="text"></b-form-input>
</div>
<b-button variant="success">Save</b-button>
</b-form-group>
</b-container>
</template>
<script>
export default {
name: 'NewsSectionCreate',
data() {
return {
headline: null,
secondaryHeadline: null,
text: null
}
},
methods: {
addText(){
console.log(this.headline, this.secondaryHeadline, this.text)
}
}
}
</script>
b-form-group is not a form it's layout that structures the label and inputs, in order to submit that inputs you should wrap the b-form-group tags with a b-form component which has #submit event:
<b-form #submit="addText">
<b-form-group >
<div class="fieldHeadline">
<label for="headline">Add headline</label>
<b-form-input type="text" name="headline" v-model="headline"></b-form-input>
</div>
<div class="fieldSecodnaryHeadline">
<label for="secondaryHeadline">Add secondary headline</label>
<b-form-input type="text" name="secondaryHeadline" v-model="secondaryHeadline"></b-form-input>
</div>
<div class="fieldText">
<label for="text">add text</label>
<b-form-input type="text" name="text" v-model="text"></b-form-input>
</div>
<b-button type="submit" variant="success">Save</b-button>
</b-form-group>
</b-form->
don't forget to add type="submit" to the b-button component.
Related
I have created step in each tabs which represent the steps in the form. I have used v-if condition to check which step should be displayed. As of now the steps work perfectly fine when i click the next button. Even if the inputs are empty I am able to go to the next step. I want some validation on each step that will check if the input is empty and add a class to that input say "error-class". How do I do that in vuejs?
This is my form in .vue file.
<form id="product_form" enctype="multipart/form-data">
<!-- One "tab" for each step in the form: -->
<button type="button" v-if="step === 2 || step === 3 || step === 4" id="prevBtn1" #click.prevent="prev()"></button>
<div v-if="step === 1" class="tab">
<h3>Post a product</h3>
<div class="preview" id="preview">
</div>
<div class="single-holder">
<input type="text" name="pname" id="pname" placeholder="Title*" required="true" ref="pname">
</div>
</div>
<div v-if="step === 2" class="tab">
<h3>Describe your Product</h3>
<div class="descrip">
<textarea name="description" id="description" placeholder="Description" required="true"></textarea>
</div>
</div>
<div v-if="step === 3" class="tab">
<h3>Set Inventory</h3>
<div class="fixed-width">
<div class="single-holder">
<label>Quantity</label>
<input type="number" name="quantity" id="quantity" required="true">
</div>
</div>
</div>
<div v-if="step === 4" class="tab">
<h3>Share On</h3>
<div class="address-details-holder clearfix">
<div class="single-holder">
<input placeholder="_ _ _ _" id="zipcode" name="zipcode" maxlength="4" type="text" #keypress="onlyNumber">
</div>
</div>
</div>
</form>
This is my method in Vuejs
methods:{
onlyNumber ($event) {
let keyCode = ($event.keyCode ? $event.keyCode : $event.which);
if ((keyCode < 48 || keyCode > 57) && keyCode !== 46) { // 46 is dot
$event.preventDefault();
}
},
prev() {
this.step--;
},
next() {
this.step++;
//if(this.step===1){
// console.log(this.$refs.name.value);
//if(this.$refs.pname.value !== null){
// this.step++;
//}
//}
}
As of now the steps work fine if i remove the if condition in the function next() in methods. But I need input validations on each step so the user has to fill out the missing data in all the form fields.
I think you can use Vee Validate . It will help you check required in each input
<input v-validate="'required'" data-vv-as="field" name="required_field" type="text">
And return error message for that input if it false
<span>{{ errors.first('email') }}</span>
corporate.html
<form #f="ngForm" name="corporateProfileForm" ng-submit="corporateFrmSave(objDS, objDSCurrency)" novalidate="">
<div class="row form-group">
<div class="col-md-12" >
<input type="text" *ngIf="formData" [(ngModel)]="formData.Corporate_Id" id="corpid" title="Corporate ID" tab-index="1" name="corpid" maxlength="20" #corpid="ngModel" required/>
<label for="corp"><b>Corporate ID</b></label>
<div *ngIf="corpid.invalid && (corpid.dirty || corpid.touched)" class="alert alert-danger">
<div *ngIf="corpid.errors.required">
Name is required.
</div>
<div *ngIf="ncorpidame.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="corpid.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>
</div>
</div>
</form>
Iam getting error message as
ERROR TypeError: Cannot read property 'invalid' of undefined
Make sure you define your variable with this structure:
TS file
export class ContactComponent implements OnInit {
myform: any;
corpid: FormControl;
constructor() {
}
ngOnInit() {
this.createFormControls();
this.createForm();
}
createFormControls() {
this.corpid= new FormControl('', Validators.required);
}
createForm() {
this.myform = new FormGroup({
corpid: this.corpid,
});
}
HTML file
<div class="md-form form-sm form-group"
[ngClass]="{
'invalid': corpid.invalid && (corpid.dirty || corpid.touched),
'valid': corpid.valid && (corpid.dirty || corpid.touched)
}">
<i class="fa fa-user prefix"></i>
<input
type="text" id="corpid" class="form-control"
required
[formControlName]="'corpid'">
<label for="corpid" class="">Your corpid</label>
</div>
<div class="form-control-feedback"
*ngIf="corpid.errors && (corpid.dirty || corpid.touched)">
<p *ngIf="corpid.errors.required">corpid is required</p>
</div>
It's hard to tell because issue is not in your HTML snipped but in .ts file.
I hope my Code will be helpfull
The issue is with the *ngIf, so when that condition is checked, Angular renders the rest of the template, and while the small fraction of time while *ngIf is being evaluated, your template reference variable corpid does not exist, so it will throw an error when trying to check the validation intially.
Wrap the input field with the validation div's inside the *ngIf instead of applying it only on the input field.
<div class="row form-group" *ngIf="formData">
<input [(ngModel)]="formData.Corporate_Id" id="corpid" ... >
<!-- more code here... -->
</div>
DEMO
I want to have two mailchimp forms ( linked to the same mailchimp list ) within the same landingpage in a Shopify Store. *it is a long landing page so I want them to be able to subscribe two times along the way.
It seems the second form does not work and the only think it does is refreshing the page. I am pretty sure there is a conflict with their ID´s because the two forms have the same ID ( id="mailchimp" ) but I believe it is neccesary for them to work.
I may have a very easy-to-resolve question but i have been struggling with it for a while. It seems there is no documentation about it ( apart from inserting one of the forms within an iframe -> I am not confortable with this solution because I want to record with GTM ( GA ) customer succesuful submitions etc. ).
The code for the forms ( snippet that it is called two times within the page ):
<!-- Newsletter Section -->
<section id="services" class="small-section bg-gray-lighter">
<div class="container relative">
<form class="form align-center newsdown" id="mailchimp">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="mb-20">
<input placeholder="Introduce tu email" class="newsletter-field form-control input-md round mb-xs-10" type="email" pattern=".{5,100}" required/>
<button type="submit" class="btn btn-mod btn-border-c btn-medium btn-round mb-xs-10">
Suscribe
</button>
</div>
<div id="subscribe-result"></div>
</div>
</div>
</form>
</div>
</section>
<!-- End Newsletter Section -->
What can I do to have these two identical forms working on the same page? Have in mind I don't have access to the javascript ( because mailchimp has Shopify app that makes this connection ).
If you wrap each mailchimp form in a ...., then run this script on the page, it will re-assign all IDs of the non-focused form, and re-bind the submit event. A bit hacky, but it works if you're in a bind.
$(document).ready(function() {
// only execute if confirmed more than 1 mailchimp form on this page
if ( $('.mc-form-instance').length > 1 ) {
$('.mc-field-group > .required').on('focus', function() {
var thisField = $(this);
// backup all mc-form ids on this page
$('.mc-form-instance [id]').each(function() {
var currentID = $(this).attr('id');
if ( currentID.indexOf('-bak') == -1 ) {
$(this).attr('id', currentID + '-bak');
}
});
// change the current form ids back to original state
var thisForm = thisField.closest('.mc-form-instance');
thisForm.find('[id]').each(function() {
var currentID = $(this).attr('id');
if ( currentID.indexOf('-bak') != -1 ) {
$(this).attr('id', currentID.replace('-bak', ''));
}
});
});
// re-bind
$.getScript('//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js');
}
});
As it appeared there were a conflict with two exact forms ( same javascript etc ) so I implemented the second form differently:
<!-- Newsletter Section -->
<section id="services" class="small-section bg-gray-lighter">
<div class="container relative">
<form action="YOURACTION;id=YOURID" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div class="row">
<div class="col-md-8 col-md-offset-2" style="text-align: center;">
<div class="newsletter-label font-alt">
¿Te interesa? Recibe más noticias y tutoriales exclusivos
</div>
<div class="mb-20">
<input name="EMAIL" id="mce-EMAIL" placeholder="Introduce tu email" class="newsletter-field form-control input-md round mb-xs-10 required email" type="email" pattern=".{5,100}" required/>
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button btn btn-mod btn-border-c btn-medium btn-round mb-xs-10">
</div>
<div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div>
</div>
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_5307a1008b76c5446a7303622_18658ede2a" tabindex="-1" value=""></div>
<div class="form-tip">
<i class="fa fa-info-circle"></i> Pocos emails, pero de calidad. Nunca Spam. Te servirán.
</div>
<div id="subscribe-result"></div>
</div>
</div>
</form>
</div>
</section>
<!-- End Newsletter Section -->
<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';fnames[2]='LNAME';ftypes[2]='text';fnames[3]='MMERGE3';ftypes[3]='dropdown';fnames[4]='MMERGE4';ftypes[4]='phone';fnames[5]='MMERGE5';ftypes[5]='url';fnames[7]='MMERGE7';ftypes[7]='text';fnames[6]='MMERGE6';ftypes[6]='birthday';fnames[8]='MMERGE8';ftypes[8]='text';fnames[9]='MMERGE9';ftypes[9]='radio';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
<!--End mc_embed_signup-->
Attention: It should work with the new forms API!
Is there a possibility to submit a raw form without any bindings of its elements?
An Example:
<div class="form-mantle">
<form (ngSubmit)="onSubmitForm1(f1.value)" #f1="ngForm">
<input ngControl="name1" name="name1" type="text" required/><br/>
<input ngControl="text1" name="text1" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!f1.form.valid">Next </button>
</form>
</div>
<pre>
{{ form1 | json }}
</pre>
How should onSubmitForm1() look like, so that I get form1 like below rendered:
{
name1: "Michael Jackson",
text1: "They don't really care about us"
}
I've already preapared a component to copy+paste, for those, who want to help:
import { Component } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'form1',
templateUrl: 'form1.component.html',
styleUrls: ['form1.component.css']
})
export class Form1Component {
form1 : any = {};
constructor() { }
onSubmitForm1 (data?:any) {
// get raw data from form without bindings
this.form1 = data;
console.log("Data", data);
return false;
}
}
Edit: The exact working copy in plnkr (http://plnkr.co/edit/nMPTYLGxgWzzJuD9Be3f?p=preview) does not work within the seed from https://github.com/mgechev/angular2-seed . Maybe it is a version problem ??
Double binding works without errors:
<div class="form-mantle">
<form (ngSubmit)="onSubmitForm1(f1.value)" #f1="ngForm">
<input [(ngModel)]="f1.name1" #name="ngModel" name="name1" type="text" required/><br/>
<input [(ngModel)]="f1.text1" #name="ngModel" name="text1" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!f1.form.valid">Next </button>
</form>
</div>
<pre>
{{ f1.value | json }}
</pre>
Just call it like so in your ngSubmit:
(ngSubmit)="onSubmitForm1(f1.value)"
To every control you want to submit add the ngControl attribute to set its name:
<input ngControl="name1" name="name1" type="text" required/><br/>
<input ngControl="text1" name="text1" type="text" required/><br/>
Then in your onSubmitForm1:
onSubmitForm1 (data?:any) {
console.log("Data", data);
this.form1 = data;
}
Plunker for example usage
Yeap, for now (rc4) you have only two ways for accepting a data after submit:
1) model-driven strategy (bindings)
2) template-driven strategy (ngControls)
Finaly the following has worked (double bindings :/ ):
<form (ngSubmit)="onSubmitForm()" #s1="ngForm">
<input [(ngModel)]="step1.name1" [ngModelOptions]="{standalone: true}" type="text" required/><br/>
<input [(ngModel)]="step1.text1" [ngModelOptions]="{standalone: true}" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!s1.form.valid">Next </button>
</form>
I have a form that I want to switch its mode and also corresponding buttons. Basically, when users open the page first, they see the form which cannot be edited. There is an "Edit" button as well. When they click the button two things will happen: 1. The form will be editable. 2. "Edit" button is hidden and another two buttons show up which are "Save" and "Cancel".
The code I have now is close but not working the way as I mentioned above. Any idea how to fix it?
html:
<div class="eq-height widget grid_4 container flat rounded-sm bspace" id="Div5">
<header class="widgetheader">
<h2>Contact</h2>
</header>
<input type="submit" value="Edit" class="edit edit-one-button btn lg bold ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-state-hover" style="border-style:Solid;"/>
<input type="submit" value="Save" class="save edit-one-button btn lg bold ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-state-hover" style="border-style:Solid;"/>
<input type="submit" value="Cancel" class="cancel edit-one-button btn lg bold ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-state-hover" style="border-style:Solid;"/>
<fieldset id="Fieldset1" class="content form-fields">
<div class="inner tspace clearfix">
<ul id="contact" class="alpha">
<li class="contactinfo">
<label class="contactinfo grid_12">
Rebekah Becker</label>
</li></ul>
</div>
</fieldset>
<fieldset id="Fieldset6" style="display:none"
class="content form-fields">
<div class="inner tspace clearfix">
<ul id="Ul1" class="alpha">
<li class="contactinfo">
<label class="contactinfo grid_4">
First Name:</label>
<input type="text" trim="true" maxlength="250" value="Rebekah" class="profile-field grid_4">
</li></ul>
<div class="clear-both"></div>
</div>
</fieldset>
</div>
css:
.save, .cancel
{
display:none;
}
javascript:
/*script to toggle the form mode*/
<script type="text/javascript">
var divheight;
$(".edit-one-button").click(function () {
var btnname = $(this).val();
if (btnname == 'Edit') {
divheight = $('.widget').attr('style');
$(this).closest('.widget').removeAttr('style');
$(this).nextUntil('.edit-one-button').toggle();
}
else {
$(this).nextUntil('.edit-one-button').toggle();
$(this).closest('.widget').attr('style', divheight);
}
});
</script>
/*script to switch the buttons*/
<script type="text/javascript">
$('.edit').click(function () {
$(this).hide();
$(this).siblings('.save, .cancel').show();
});
$('.cancel').click(function() {
$(this).siblings('.edit').show();
$(this).siblings('.save').hide();
$(this).hide();
});
$('.save').click(function() {
$(this).siblings('.edit').show();
$(this).siblings('.cancel').hide();
$(this).hide();
});
</script>
this is to do the exact thing as you said in top.
$(document).ready(function(){
$("#edit").click(function(){
$('#Fieldset1').hide();
$('#Fieldset6').show();
$('#edit').hide();
$('#save').show();
$('#cancel').show();
});
});
</script>
if you want me to do the rest of the cancel and save please let me know :)