I am trying to increase the height of slider/track of slider component.
I have been trying to set style and sliderStyle, but no luck yet.
I was looking at the code and it seems does not allow us to set css style down to that level.
return (
<div {...other} style={prepareStyles(Object.assign({}, style))}>
<span>{description}</span>
<span>{error}</span>
<div
style={prepareStyles(Object.assign({}, styles.slider, sliderStyle))}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onMouseUp={this.handleMouseUp}
onTouchStart={this.handleTouchStart}
onKeyDown={!disabled && this.handleKeyDown}
>
<div ref={(node) => this.track = node} style={prepareStyles(styles.track)}>
<div style={prepareStyles(styles.filled)} />
<div style={prepareStyles(styles.remaining)} />
<div
ref={(node) => this.handle = node}
style={prepareStyles(handleStyles)}
tabIndex={0}
>
{!disabled && !disableFocusRipple && (
<FocusRipple
style={rippleStyle}
innerStyle={styles.rippleInner}
show={(hovered || focused) && !active}
color={styles.rippleColor.fill}
/>
)}
</div>
</div>
</div>
<input
type="hidden"
name={name}
value={value}
required={required}
min={min}
max={max}
step={step}
/>
</div>
);
Any thought on that?
Thanks,
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 have created a React component using redux-form and am looking to autoFocus on the first field. The fields are created by looping through an object and creating a field for each item in that object. When I use autoFocus in the JSX is autoFocuses on the last field in the form (which makes sense).
Does anyone know how I can autoFocus on the first field in the form?
Here is my component:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
class BalanceForm extends Component {
constructor(props) {
super(props);
this.submitForm = this.submitForm.bind(this);
this.cancel = this.cancel.bind(this);
}
cancel() {
//not relevant
}
submitForm(e, values) {
//not relevant
}
render() {
return (
<div>
{this.props.balanceFormVisible &&
<div className="modal-background">
<div className="modal">
<form onSubmit={this.submitForm}>
{Object.keys(this.props.accounts).map((key) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
</div>
)
})}
<button type="submit">Submit</button>
<button onClick={ this.cancel } className="cancelbtn" >Cancel</button>
</form>
</div>
</div>
}
</div>
);
}
}
BalanceForm = reduxForm({form: 'balance'})(BalanceForm)
export default BalanceForm;
Thanks in advance :)
Solution to this was to conditionally render the form field. Thanks to Alexander Borodin for the inspiration...
{Object.keys(this.props.accounts).map((key, i) => {
console.log(key, i)
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
{(i === 0) ? (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
) : (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
/>
)}
</div>
)
})}
Some of these either didn't compile or are a bit verbose. This worked for me:
{Object.keys(item)
.map((key, i) =>
<div className={`form-row ${key}`} key={key}>
<label>{key}</label>
<input value={item[key]}
type='text'
onChange={e => {
this._updateValue(key, e.target.value);
}}
autoFocus={i === 0}
/>
</div>
)}
Alternatively, if you hook in to ComponentDidMount, you can ask the DOM to focus the first existing field within the form.
Add a ref to the form
<form onSubmit={this.submitForm} ref='form'>
Use the ref to focus the element after mounting
componentDidMount() {
const firstInput = this.refs.form.querySelector('input')[0];
firstInput && firstInput.focus();
}
Try this:
{Object.keys(this.props.accounts).map((key, i) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
{ (i === 0) ? 'autoFocus': ''}
/>
</div>
)
})}
I ran into an issue where autoFocus wasn't properly passing down from Field to the underlying component. Had to explicitly pass autoFocus in the props prop for Field.
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-->
I'm trying to impose validation based on a change of one field onto another field inside a formGroup which is inside a FormArray of multiple instances of this group. I'm using mydatepicker on one of the fields. For example, when the date is changed, I then want the Reason for change field in that group only to be validated to check to make sure the first option (value of 0) is not selected. I have 2 problems with this:
When I change the date, the Reason for change field does not get checked for validity right away. It only happens AFTER I change the value of the field to 1 and then to 0. It's default is set to 0 and it should immediately pick this up when I change the date.
When it does finally realize the form is invalid, it does it for ALL the update buttons rather than just the one in the FormGroup whose Date field I have changed.
ts file code:
subscribeDateChange(formGroup){
(<any>this.rfcActionTasksForm).controls.tasks.controls[0].controls['DueDate'];
const tasks = formGroup;
const changes$ = tasks.controls['DueDate'].valueChanges;
changes$.subscribe(dd => {
var arrayControl = this.rfcActionTasksForm.get('tasks') as FormArray;
var item = arrayControl.at(1);
console.log(item);
if(tasks.value['ReasonForChangeId'] == '0'){
tasks.controls['ReasonForChangeId'].setValidators(Validators.pattern(/([1-9])/));
}
});
}
ngOnInit() {
this.rfcActionTasksForm = this._fb.group({
tasks: this._fb.array([this.buildTask()])
});
}
buildTask(): FormGroup {
return this._fb.group({
Id: '',
Action: ['', Validators.required],
Step: '',
AssignedToId: ['', Validators.required],
AssignedToColour: '',
DueDate: ['', Validators.required],
ReasonForChangeId: '',
OriginalDueDate: '',
Completed: '',
OverDue: ''
},{
validator: (formGroup: FormGroup) => {
//return this.validateDays(formGroup);
//console.log(formGroup.controls['DueDate']);
//this.subscribeDateChange(formGroup.controls['DueDate'], formGroup.controls['ReasonForChangeId']);
return this.subscribeDateChange(formGroup);
}
});
}
html:
<form class="multi-col implementation" *ngIf="rfc.Plan [formGroup]="rfcActionTasksForm">
<div class="task-item" formArrayName="tasks" *ngFor="let task of tasks.controls; let i = index">
<div [formGroupName]="i">
<div class="row header-row">
<div class="col-md-12">
<h5 class="no-margin">Step {{i + 1}}</h5>
<input
[style.display]="'none'"
formControlName="Step">
<input
[style.display]="'none'"
formControlName="AssignedToColour">
<input
[style.display]="'none'"
formControlName="Id">
</div>
</div>
<div class="input-row row">
<div class="col-md-11">
<label for="{{'task' + i}}">Action:</label>
<div
[ngClass]="{'has-error': (tasks.get(i + '.Action').touched || tasks.get(i + '.Action').dirty) && !tasks.get(i + '.Action').valid }">
<textarea
rows="6"
id="{{'task' + i}}"
formControlName="Action"></textarea>
<span class="help-block" *ngIf="(tasks.get(i + '.Action').touched || tasks.get(i + '.Action').dirty) && tasks.get(i + '.Action').errors">
<span *ngIf="tasks.get(i + '.Action').errors.required">
Please enter a title.
</span>
</span>
</div>
</div>
<div class="col-md-1 text-center">
<label>Status</label>
<i *ngIf="tasks.get(i + '.Completed').value" class="glyphicon glyphicon-ok-sign ok" title="Completed"></i>
<i *ngIf="!tasks.get(i + '.Completed').value && !tasks.get(i + '.OverDue').value" class="glyphicon glyphicon-minus-sign pending" title="In progress"></i>
<i *ngIf="!tasks.get(i + '.Completed').value && tasks.get(i + '.OverDue').value" class="glyphicon glyphicon-exclamation-sign text-danger" title="Overdue!"></i>
</div>
</div>
<div class="input-row row">
<div class="col-md-3 assigned-to">
<div
[ngClass]="{'has-error': (tasks.get(i + '.AssignedToId').touched || tasks.get(i + '.AssignedToId').dirty) && !tasks.get(i + '.AssignedToId').valid }">
<label for="{{'assignedTo' + i}}">Assigned to:</label>
<div class="color-block" [style.background]="tasks.get(i + '.AssignedToColour').value"></div>
<label class="fa select">
<select
*ngIf="users"
id="{{'assignedTo' + i}}"
formControlName="AssignedToId">
<option
*ngFor="let user of users | trueValueFilter: 'IsActive'"
[value]="user.Id">{{user.Name}}</option>
</select>
</label>
<span class="help-block" *ngIf="(tasks.get(i + '.AssignedToId').touched || tasks.get(i + '.AssignedToId').dirty) && tasks.get(i + '.AssignedToId').errors">
<span *ngIf="tasks.get(i + '.AssignedToId').errors.required">
Please select a user.
</span>
</span>
</div>
</div>
<div class="col-md-3">
<div
[ngClass]="{'has-error': (tasks.get(i + '.DueDate').touched || tasks.get(i + '.DueDate').dirty) && !tasks.get(i + '.DueDate').valid }">
<label for="{{'dueDate' + i}}">Due date:</label>
<my-date-picker
class="datepicker"
type="text"
id="{{'dueDate' + i}}"
formControlName="DueDate"
[options]="myDatePickerOptions"></my-date-picker>
<span class="help-block" *ngIf="(tasks.get(i + '.DueDate').touched || tasks.get(i + '.DueDate').dirty) && tasks.get(i + '.DueDate').errors">
<span *ngIf="tasks.get(i + '.DueDate').errors.required">
Please set a due date.
</span>
</span>
</div>
</div>
<div class="col-md-2">
<label for="{{'reason' + i}}">Reason for change:</label>
<label class="fa select">
<select
class="reason-select"
*ngIf="reasons"
id="{{'reason' + i}}"
formControlName="ReasonForChangeId">
<option
*ngFor="let reason of reasons"
[value]="reason.Id">{{reason.Reason}}</option>
</select>
</label>
</div>
<div class="col-md-3">
<div class="text-center">
<label for="{{'OriginalDueDate' + i}}">Original due date:</label>
<span>{{tasks.get(i + '.OriginalDueDate').value | dateToStringFilter}}</span>
<input
readonly
type="text"
id="{{'OriginalDueDate' + i}}"
[style.display]="'none'"
formControlName="OriginalDueDate">
</div>
</div>
<div class="col-md-1">
<div class="text-center">
<label for="{{'completed' + i}}">Completed:</label>
<div class="checkbox-group">
<input type="checkbox"
type="checkbox"
id="{{'completed' + i}}"
formControlName="Completed">
<label class="checkbox" for="{{'completed' + i}}"></label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div>
<button
class="glyphicon glyphicon-plus-sign btn-icon add"
title="Insert task after this one"
(click)="insertTaskField(i)"></button>
<button
class="glyphicon glyphicon-remove-sign btn-icon delete"
title="Delete this task"
(click)="removeTaskField(i, tasks.get(i + '.Id')?.value)"></button>
<button
*ngIf="!tasks.get(i + '.Id').value"
(click)="saveNewTask(rfc.Id, i);"
[disabled]="!rfcActionTasksForm.valid"
class="pull-right">Save new</button>
<button
*ngIf="tasks.get(i + '.Id')?.value"
[disabled]="!rfcActionTasksForm.valid"
(click)="updateTask(i, tasks.get(i + '.Id')?.value)"
class="pull-right">Update</button>
</div>
</div>
</div>
</div>
</div>
<div class="row last">
<div class="col-md-12">
<button
class="pull-right"
[disabled]="enableUpdateAll === false"
(click)="reOrderTasks()">Update All</button>
</div>
</div>
</form>
I see multiple problems here:
A validator should be of the form:
(control: AbstractControl): {[key: string]: any} => {
if(isValid(control))
return null;
else
return {"myValidator":"invalid thing detected"};
}
You are returning undefined everytime so it can't work.
You cannot subscribe because it means everytime you make a change in your form, you resubscribe to the whole group's valuechanges, that's non-sense.
Forget about valueChanges, you need to do your control synchronously. Check if there is an error and use the setError() method of your children controls.
something like :
(group: FromGroup): {[key: string]: any} => {
if(!isValid(group)){
group.get("myChildControl").setErrors({"localError":"error detected !"});
return {"groupError":"error detected !"};
}
return null;
}
I'm not sure if you should use the second parameter of setError(errors,{emitEvent:false}) to avoid propagation or not.