I have this Formik Form with Yup validation :
<Form>
<div className="mt-3">
<label className="font-semibold">Nom</label>
<Field className={`mt-2 rounded-md w-full py-2 px-3 ${errors.lastname ? 'border-2 border-red-500 error-form error-form' : 'border'}`}
name="lastname"
type="text"
placeholder="Votre nom"
/>
{errors.lastname &&
<div className="text-red-500 text-sm">{errors.lastname}</div>}
[...]
</div>
I disable the verification before submit (because I didn't want the visitor to be alarmed on every input even before he filled it :
validateOnChange={false}
validateOnBlur={false}
Everything works fine. But now I want to set a green border on the input (when I click on Submit button) to the Fields that are OK for Yup.
I already do it with red borders when error.
I tried className={`mt-2 rounded-md w-full py-2 px-3 ${errors.message ? 'border-2 border-red-500 error-form' : 'border'} ${!errors.lastname ? 'border-2 border-green-500' : ''}`} but this set all my fields in green border even before the submit.
Any idea ?
Yes, it will be applied before you even submit the form as you're just checking if it has error or not. Obviously in the beginning, since there are no errors, all borders will be painted green.
Apply the same code conditionally on submit button click and it will work.
Or to make things more clean, you can dynamically add a class like form_submitted on submit click and then use the following CSS
.form_submitted input {
border-color: green;
}
.form_submitted input.error {
border-color: red;
}
Related
I have a laravel component for a submit button in Tailwind.
The button code is:
<div class="{{ $position }} mt-4">
<button type="submit"
class="inline-flex items-center h-10 px-5 text-indigo-100 bg-indigo-600 rounded-lg focus:shadow-outline hover:bg-indigo-800" style="{{ addShadow() }}"
#if (!empty($onClick))
onclick="{{ $onClick }}"
#endif
>
#fas('{{ $icon }}')
<span class="ml-2">{{ $label }}</span>
</button>
The things like position, icon, label, onclick are passed in OK.
My problem is that unless the mouse is over the button it deos not really appear as can be seen from the image attach. The first shows as the page opens and the second is as the mouse is over.
I simply cannot get this to work!
I normally actually upload and test in an online area, but with the new Laravel Vite changes are not made. If this is done in localhost and then uploaded the app.css etc it works.
I am using formvalidation.io and Tailwind. Whilst there are plugins for many of the major frameworks, there does not appear to be one for Tailwind.
My issue is trying to get the error messages to appear below the form input to which they relate. There are five inputs, all along the same lines :
<div class="relative w-full mb-3">
<label class="block uppercase text-thatblue text-xs font-bold mb-2" for="password">Password</label>
<input type="password" name="password" id="password" class="border-0 px-3 py-3 placeholder-thatblue-lightest text-thatblue bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150" placeholder="Password">
</div>
If I put in an empty div with an ID of "messages" at the bottom of the form input I can get the error messages to display in that div using :
message: new FormValidation.plugins.Message({
clazz: 'text-xs text-red-500',
container: '#messages'
},
}),
...but that's not a great visual layout.
If, however, I put in an empty div with class of messages under each of the inputs
<div class="messages"></div>
And then change the container targeted by formvalidation.io to be
container: '.messages'
...then error messages for all five inputs appear against the first input, which is even less ideal.
The documentation suggests that I can target closest siblings using :
message: new FormValidation.plugins.Message({
clazz: 'text-xs text-red-500',
container: function (field, ele) {
return FormValidation.utils.closest(ele, '.messages').nextElementSibling;
},
}),
But this does nothing.
What am I missing, Obi Wan? You're my only hope.
I have those purple lines ( as my screen bellow ).
I doing some conditionnal rendering, I'd like to know if I can remove all those purple lines.
I've heard removing all divs and adding React.Fragments might help, this what I've done so far. But the issue is still there.
If anyone could tell where the issue might come from, I'd be grateful !
the main view / Render 1
<div className="user-infos">
<h4><u> Parameters </u></h4>
{ (componentState == "edit") ?
<form >
<Render 3/>
</form>
: (componentState == "index") ?
<Render 2/>
: (componentState == "delete") ?
<React.Fragment>
<p> Are you sure you want to leave us ? </p>
<p> If yes, you have to type your email and press "confirm".</p>
<form>
<input type="text" />
<input type="submit" value="confirm email"/>
</form>
<span>
<button> Delete ur account</button>
<button> Cancel </button>
</span>
</React.Fragment>
: ""
}
</div>
Render 2
return (
<React.Fragment>
<p> Username : John </p>
<p> Timezone : London </p>
<span>
<button> Edit Profile </button>
<button> Delete account </<button>>
</span>
</React.Fragment>
Render 3
return (
<React.Fragment>
<label for="email"> Username :
<input type="text"/>
</label>
<label for="text"> Timezone :
<span>
<select
onChange={options}
<options>
</select>
</span>
</label>
<button type="submit"> Save Profile </button>
<button> Cancel </button>
</React.Fragment>
);
By default, chrome adds styling to your html. In the case of <p>, it adds the following css to your element.
If you want the margin to disappear, you need to set margin: 0; on your <p> element to overwrite chrome's styling.
The purple dash line occurs when there is available space for the elements to expand into. See here. From what I can tell from comparing flexboxes with other display types, the purple dash with purple background is specifically for space inside flexboxes (display:flex in CSS).
Would need to see your CSS to be sure, but I imagine there's justify-content: space-between telling the flexbox to evenly distribute the remaining empty space between the elements as well as flex-direction: column telling the flexbox to stack the child elements vertically.
If that's the case, you can remove justify-content: space-between and use flexbox styling to change things to how you want it to look. I found this website helpful: A Complete Guide to Flexbox
I have a project where I need to do form validation. If the fields are not correctly entered the formErrors object will get a string variable with the correct error text. So in the case of email the error String will be put in formErrors.email. This String can be printed out in the p element that shows the error even the visibility of this p element can be shown or hidden depending on the state of formErrors.email like v-if="formErrors.email".
But when I try to give the input element a red border color using :class="{formErrors.email : text-red-primary}" the linter throws an error Parsing error: Unexpected token .. But how do i enable this class binding with a variable inside the formErrors object.
<input
type="text"
name="email"
id="email"
v-model="email"
placeholder="Email address"
class="w-full px-4 py-3 border rounded-lg text-black-primary focus:outline-none text-sm"
:class="{formErrors.email : text-red-primary}"
/>
<p v-if="formErrors.email" class="text-red-primary text-xs mt-1 ml-1">{{formErrors.email}}</p>
</div>
Your class binding is currently backwards: the key should be the class name, and the value should be truthy/falsy (e.g., a non-empty string would be truthy). Also, the key (text-red-primary) needs to be quoted because it contains non-alphanumeric characters (-):
<!-- ❌ -->
<input :class="{ formErrors.email : text-red-primary }">
<!-- ✅ -->
<input :class="{ 'text-red-primary' : formErrors.email }">
You can create computed property say isEmailInValid which return true/false
and use it in template like this
:class="{'text-red-primary': isEmailInValid}"
dynamic class gets applied when condition is true only.
You can checkout vue docs for more info https://v2.vuejs.org/v2/guide/class-and-style.html
I'm trying to style a component properly. At the moment, the table works beautifully, but the style of it isn't ideal, and usually this would be easy to fix with tailwind but the components layout makes it very confusing to know exactly how to style it.
This is the example I am referencing,
https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink
Now specifically what I want to change is the group functions. Currently the use emoji's to work, I really want to to be a proper button so users understand very clearly the functionality of the component, as below.
<table className="w-full text-md bg-white shadow-md rounded mb-4" {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th className={td_header} {...column.getHeaderProps()}>
<div>
{column.canGroupBy ? (
// If the column can be grouped, let's add a toggle
<span {...column.getGroupByToggleProps()}>
{column.isGrouped ? 'Click to Un-Group 🛑 Click to Sort!' : ' Click to Group 🔮 Click to Sort!'}
</span>
) : null}
<span {...column.getSortByToggleProps()}>
{column.render('Header')}
{/* Add a sort direction indicator */}
{column.isSorted
? column.isSortedDesc
? ' 🔽'
: ' 🔼'
: ''}
</span>
</div>
{/* Render the columns filter UI */}
<div>{column.canFilter ? column.render('Filter') : null}</div>
</th>
))}
Now ideally I want something like this for the group and filter toggle, taken from tailwind
https://tailwindcss.com/components/buttons
<div class="inline-flex">
<button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-l">
Group
</button>
<button class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r">
Filter
</button>
</div>
How does one go about styling this effectively, given the string it is using is not a component and does not have any styling that I can see involved?
Thanks in advance,
The string present in your question is not a component, but it easily could be. Those elements don't necessarily need to be strings; react-table is a headless library, so you're free to change the visuals the way you want. There are a variety of possible solutions here. One solution would be to replace the entire ternary by defining a custom functional component for that sort icon:
const sortIcon = (sorted, sortedDesc) => {
if (sortedDesc) {
return (<h1> this is arbitrary </h1>);
} else if (sorted) {
return (<h2> more arbitrary </h2>);
} else {
return null;
}
}
and then replacing the ternary:
<span {...column.getSortByToggleProps()}>
{column.render('Header')}
{/* Add a sort direction indicator */}
{sortIcon(column.isSorted, column.isSortedDesc)}
</span>
This is a bad way to do it, probably, and untested beside that, but the point is that the HTML/JSX stuff is arbitrary. Those emoji strings can be replaced with valid JSX in any form. You could do a similar thing with the column.isGrouped ternary, as well! It may be worth looking at some JSX tutorials if you're not already familiar, or re-familiarizing yourself with exactly what a column Object contains if you want to continue to add functionality.
(link caveat: each of the different useX hooks adds more stuff to the column/row/etc Objects, so I just linked the core useTable one)