I would like to implement a date timepicker with Algolia. If I choose a date, all elements should be displayed from this date.
Unfortunately, I have no idea how I can make this with Agolia.
I hope you can help me.
const datePicker = instantsearch.connectors.connectRange(
(options, isFirstRendering) => {
if (!isFirstRendering) return;
new Calendar({
element: $('.daterange--single'),
current_date: new Date(),
format: {input: 'DD.MM.YYYY'},
required: false,
callback: function() {
const start = new Date().getTime();
refine([start]);
},
});
}
);
search.addWidget(
datePicker({
attributeName: 'date',
})
);
<div class="daterange daterange--single"></div>
now i have a working code. Now a have the problem.. how i can change in my custom widget the searchParameters?
const search = instantsearch({
appId: '0000000',
apiKey: '000000000000',
indexName: 'Events',
routing: true,
searchParameters:{
filters: 'dateNumeric >= 1531591200'
}
});
var customWidget = {
init: function(options) {
$( "#datetimepickerNotime" ).focusout(function() {
var date = $('#datefromdatetimepicker').val();
var date = new Date (date);
alert("dateNumeric >= 1512752400");
});
}
};
search.addWidget(customWidget);
<div class='input-group date' id="datetimepickerNotime">
<input type='text' id="datefromdatetimepicker" name="date" class="form-control" autocomplete="off" value="<f:format.date date='now' format='d.m.Y' />"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
import { Formik, Field } from 'formik';
import { connectRange } from 'react-instantsearch-dom';
import * as Yup from 'yup';
const RangeFilter = ({ currentRefinement, min, max, refine }) => {
const validationSchema = Yup.object().shape({
minValue: Yup.number().min(min, `Minimum value must be at least ${min}`),
maxValue: Yup.number().max(max, `Maximum value must be at most ${max}`),
});
const onSubmit = (values) => {
refine({ min: values.minValue, max: values.maxValue });
};
return (
<Formik
onSubmit={onSubmit}
validationSchema={validationSchema}
initialValues={{
minValue: currentRefinement?.min,
maxValue: currentRefinement?.max,
}}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field name="minValue">
{({ field, form: { errors, touched } }) => (
<div>
<label htmlFor="price-min">To price:</label>
<input
className="input is-shadowless"
{...field}
id="price-min"
type="number"
placeholder="Min price"
/>
{errors.minValue && touched.minValue && (
<p className="help is-danger">{errors.minValue}</p>
)}
</div>
)}
</Field>
<Field name="maxValue">
{({ field, form: { errors, touched } }) => (
<div className="mt-2">
<label htmlFor="price-max">From price:</label>
<input
{...field}
id="price-max"
type="number"
className="input is-shadowless"
placeholder="Max price"
/>
{errors.maxValue && touched.maxValue && (
<p className="help is-danger">{errors.maxValue}</p>
)}
</div>
)}
</Field>
<button type="submit" className="ais-RefinementList-showMore mt-2">
Get Result
</button>
</form>
)}
</Formik>
);
};
export default connectRange(RangeFilter);
Related
I am trying to implement tailwindcss styles into Formik to style forms. But the styles declared through className are not being applied?
I think Formik is using classname to define input type and tailwind uses the same method to declare styles?
my form page:
import React from "react";
import * as yup from "yup"
import { Formik, Form } from 'formik'
import { MyTextInput } from "../components/FormParts";
let mainFormSchema = yup.object().shape({
name: yup.string().trim().required()
})
const tryMainForm = () => {
const initValues = {
name: ''
}
return (
<div>
<h1>Any place in your app!</h1>
<Formik
initialValues={initValues}
validationSchema={mainFormSchema}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
<MyTextInput
label="name"
name="name"
type="text"
placeholder="name"
/>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
</Formik>
</div>
)
}
export default tryMainForm
formpart component:
import { useField } from "formik";
export const MyTextInput = ({ label, ...props }) => {
const [field, meta] = useField(props)
return (
<>
<label htmlFor={props.id || props.name} className="block text-sm font-medium text-gray-700">{label}</label>
<input className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" {...field} {...props} />
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
)
}
can you suggest a way to deal with this?
tailwind applies styles properly to label but doesn't with input?
I want to use vue3 together with bootstrap 4/5 with veevalidate 4.
<template>
<Form as="form" #submit.prevent="onFormSubmit" class="needs-validation" :class="{ 'was-validated': wasValidated }">
<div class="form-group">
<label for="firstNameId">First Name *</label>
<Field name="firstname" as="input" id="firstNameId" type="text" rules="required|firstname" class="form-control" placeholder="First Name" v-model="firstName" aria-describedby="input-true input-false input-help" aria-invalid="true" />
<ErrorMessage as="div" name="firstname" v-slot="{ message }">
{{ message }}
<div class="invalid-feedback">
{{ message }}
</div>
</ErrorMessage>
<div class="valid-feedback">Good!</div>
</div>
<Form>
</template>
<script>
import { Field, Form, ErrorMessage, defineRule } from 'vee-validate';
defineRule('required', value => {
if (!value || !value.length) {
return 'This field is required.';
}
return true;
});
defineRule("firstname", (value) => {
if (!/^[a-zA-Z0-9( ),'.:/-]+$/i.test(value)) {
return "Please use only letters, numbers and the following special characters: ( ),'.:/-";
}
return true;
});
export default {
components: {
Form,
Field,
ErrorMessage
},
data () {
return {
firstName: "",
wasValidated: false,
},
methods: {
onFormSubmit(values) {
alert(JSON.stringify(values, null, 2));
console.log("Submitted");
console.log(values);
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
this.wasValidated = true;
}, false);
});
},
},
};
</script>
The problem is that I can't activate the div with the class invalid-feedback or valid-feedback.
I could add the class was-validated to the <form>-tag, but I get feedback first after the second click on the submit button.
<template>
<Form as="form"
#submit="onFormSubmit"
class="needs-validation"
:validation-schema="schema"
v-slot="{ errors }"
>
<div class="form-group">
<label for="firstNameId">First Name *</label>
<Field
name="firstName"
type="text"
placeholder="First Name"
v-model="firstName"
aria-describedby="input-true input-false input-help"
aria-invalid="true"
v-slot="{ meta, field }"
>
<input
v-bind="field"
name="firstName"
type="text"
class="form-control"
:class="{
'is-valid': meta.valid && meta.touched,
'is-invalid': !meta.valid && meta.touched,
}"
/>
</Field>
<ErrorMessage as="div" name="firstname" v-slot="{ message }" class="invalid-feedback">
{{ message }}
</ErrorMessage>
<Form>
</template>
<script setup>
import { markRaw } from 'vue';
import { Field, Form, ErrorMessage} from 'vee-validate';
import * as yup from 'yup';
</script>
<script>
export default {
components: {
Form,
Field,
ErrorMessage
},
data () {
return {
schema: markRaw(yup.object().shape({
firstName: yup.string().min(0).max(20).label('First Name'),
})),
};
},
methods: {
onFormSubmit(values) {
console.log(JSON.stringify(values, null, 2));
},
},
};
</script>
I have a form which ultimately will be used as the UI to make some API calls to Open weather map.
Right now when I submit the a zip code in the input field, upon submission [object Object] propagates the field like in the screen shot below.
The call to the API is working as I am getting the JSON for the correct zip code...
But shouldn't this in the handleSubmit take care of everything i.e. using Object.assign to create new state and then using form.zipcode.value = ''; to clear out the input?
Thanks in advance!!
handleSubmit(event) {
event.preventDefault();
var form = document.forms.weatherApp;
api.getWeatherByZip(this.state.zipcode).then(
function(zip) {
console.log('zip', zip);
this.setState(function() {
return {
zipcode: Object.assign({}, zip),
};
});
}.bind(this)
);
form.zipcode.value = '';
}
I have enclosed all of the component's code here.
import React, { Component } from 'react';
import * as api from '../utils/api';
import '../scss/app.scss';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
zipcode: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
zipcode: event.target.value,
});
}
handleSubmit(event) {
event.preventDefault();
var form = document.forms.weatherApp;
api.getWeatherByZip(this.state.zipcode).then(
function(zip) {
console.log('zip', zip);
this.setState(function() {
return {
zipcode: Object.assign({}, zip),
};
});
}.bind(this)
);
form.zipcode.value = '';
}
render() {
return (
<div className="container">
<form name="weatherApp" onSubmit={this.handleSubmit}>
<h2>Open Weather App</h2>
<div className="row">
<div className="one-half column">
<label htmlFor="insertMode">Insert your location</label>
<input
name="zipcode"
className="u-full-width"
placeholder="please enter your zipcode"
type="text"
autoComplete="off"
value={this.state.zipcode}
onChange={this.handleChange}
/>
</div>
<div className="one-half column">
<label htmlFor="showMin">show minimum</label>
<input type="checkbox" />
<label htmlFor="showMax">show maximum</label>
<input type="checkbox" />
<label htmlFor="showMean">show mean</label>
<input type="checkbox" />
</div>
</div>
<div className="row">
<div className="two-half column">
<input type="submit" value="Submit" />
</div>
</div>
</form>
</div>
);
}
}
You should let react manage the changes to the DOM rather that editing it manually. As the value of your input field is already bound to this.state.zipcode to reset it just invoke this.setState({zipcode: ''}) instead of form.zipcode.value='';.
In the following code I have two checkboxes. On-click, they change the state of the component to their respective values.
I am building a form that will need over 100 checkboxes and I don't want to write the "onChange" function for each checkbox.
Is there a way that I can write one OnChange function that will take a parameter, then set the state to that parameter?
I've tried many ways but this is still blocking me.
Thank you!
import React from 'react';
export default class InputSearch extends React.Component {
constructor(props) {
super(props);
this.state = {
inputInternship: '',
inputMidLevel: '',
};
this.handleSubmit = this.handleSubmit.bind(this);
this.onChangeInternship = this.onChangeInternship.bind(this);
this.onChangeMidLevel = this.onChangeMidLevel.bind(this);
}
handleSubmit(e) {
e.preventDefault();
this.props.getJobData(this.state);
}
onChangeInternship(e) {
this.setState({
inputInternship: !this.state.inputInternship,
});
this.state.inputInternship == false? this.setState({ inputInternship: e.target.value }) : this.setState({ inputInternship: '' })
}
onChangeMidLevel(e) {
this.setState({
inputMidLevel: !this.state.inputMidLevel,
});
this.state.inputMidLevel == false? this.setState({ inputMidLevel: e.target.value }) : this.setState({ inputMidLevel: '' })
}
render() {
return (
<div className="search-form">
<form onSubmit={this.handleSubmit}>
<input type="checkbox" value="level=Internship&" checked={this.state.inputInternship} onChange={this.onChangeInternship} /> Internship <br />
<input type="checkbox" value="level=Mid+Level&" checked={this.state.inputMidLevel} onChange={this.onChangeMidLevel} /> Mid Level <br />
<div>
<button
type="submit"
>Search
</button>
</div>
</form>
</div>
);
}
}
You need to create a function that would return specific onChange function:
import React from 'react';
export default class InputSearch extends React.Component {
constructor(props) {
...
this.onChange = this.onChange.bind(this);
}
...
onChange(fieldName) {
return (event) => {
this.setState({
[fieldName]: !this.state[fieldName],
});
if (this.state[fieldName]) {
this.setState({ [fieldName]: '' })
} else {
this.setState({ [fieldName]: e.target.value })
}
}
}
...
render() {
return (
<div className="search-form">
<form onSubmit={this.handleSubmit}>
<input type="checkbox" value="level=Internship&" checked={this.state.inputInternship} onChange={this.onChange('inputInternship')} /> Internship <br />
<input type="checkbox" value="level=Mid+Level&" checked={this.state.inputMidLevel} onChange={this.onChange('inputMidLevel')} /> Mid Level <br />
<div>
<button
type="submit"
>Search
</button>
</div>
</form>
</div>
);
}
}
By the way, are what is the point of changing state twice in your onChangeXYZ functions?
{
this.setState({
[fieldName]: !this.state[fieldName],
});
if (this.state[fieldName]) {
this.setState({ [fieldName]: '' })
} else {
this.setState({ [fieldName]: e.target.value })
}
}
My entire application is built on different react classes and displayed like this:
MainLayout = React.createClass({
render() {
return (
<div id="body">
<Header />
<main className="container">{this.props.content}</main>
<Footer />
</div>
);
}
});
All my front-end is built in react classes like the one below:
InsertData = React.createClass({
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(),
Type: $("post2").val(),
dateAdded: new Date(),
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData />
</div>
);
}
});
Insert data to my collection works fine. I would like to render the inserted data onto the page from the <DisplayData /> component:
DisplayData = React.createClass({
render(){
var posts = Posts.find().fetch();
var postList = posts.map(function(posts){
return posts;
})
return <p> Your collection </p>
}
});
I'm rather stuck here, and not really sure how to iterate through the collection and render it in a list-structure for example. Here is my collection so far:
Posts = new Mongo.Collection('posts');
Posts.allow({
insert: function(){
return true;
},
update : function(){
return true;
},
remove : function(){
return true;
}
});
Here is a demo of how you can approach this: http://codepen.io/PiotrBerebecki/pen/bwmAvJ
I'm not sure about the format of your posts collection, but assuming that it is just a regular array, for example var posts = ['One', 'Two'];, you can render the individual post as follows:
var DisplayData = React.createClass({
render(){
var posts = ['One', 'Two'];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});
Here is the full code from my codepen.
var InsertData = React.createClass({
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(),
Type: $("post2").val(),
dateAdded: new Date(),
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData />
</div>
);
}
});
var DisplayData = React.createClass({
render(){
var posts = ['One', 'Two'];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});
ReactDOM.render(
<InsertData />,
document.getElementById('app')
);
You need to pass posts to your view component DisplayData as props, so in this case after you inserted a post, you should update your state in the InsertData component. Actually it would be better if you do the insertion login inside a service rather than the component itself, but for simplicity right now you can check the following code:
InsertData = React.createClass({
getInitialState: function() {
return {posts: []}; // initialize the state of your component
},
insertToCollection(event) {
event.preventDefault();
console.log(this.state.message + " state med message");
var content = Posts.find().fetch();
Posts.insert({
Place: $("post1").val(), // better to retrieve these values from state. You can use `handleChange` method to keep track of user inputs
Type: $("post2").val(),
dateAdded: new Date(),
}, function(err, data){
var posts = this.state.posts || [];
posts.push(data);
this.setState({posts: posts}); //after setting the state the render method will be called again, where the updated posts will be rendered properly
});
},
handleChange(event) {
this.setState({
message: event.target.value
})
console.log(this.state + " mer state her");
function insert(event) {
event.preventDefault();
console.log("added stuff");
}
},
render() {
return (
<div>
<form onSubmit={this.insertToCollection}>
<input type='text' placeholder="Select a restaurant" className="input-field"
onChange={this.handleChange} id="post1"/>
<input type='text' placeholder="What type of food they have" className="input-field"
onChange={this.handleChange} id="post2"/>
<button className="waves-effect waves-light btn btn-block" onChange={this.insert}> Submit </button>
</form>
<DisplayData posts={this.state.posts}/>
</div>
);
}
});
var DisplayData = React.createClass({
render(){
var posts = this.props.posts || [];
var renderPosts = posts.map(function(post, index) {
return (
<li key={index}>{post}</li>
);
});
return (
<div>
<p> Your collection </p>
<ul>
{renderPosts}
</ul>
</div>
);
}
});