How to target css style of the submit button with vue-formulate - vue-formulate

I have a border hover effect on the wrapper around labels and input fields. How can I remove/override the wrapper border and hover effect for the submit type? I'm using tailwind, but I'm mostly having issues targeting the correct class.
Here's my CSS
<style>
.formulate-input {
#apply my-8;
}
.formulate-input-wrapper {
#apply border-2 border-regal-blue-400;
}
.formulate-input-wrapper:hover {
#apply border-red-900;
}
.formulate-input-label {
#apply px-4 pt-3 pb-2 text-lg block w-full bg-regal-blue-400;
}
.formulate-input-element input,
.formulate-input-element textarea,
.formulate-input-element select {
#apply pb-4 px-4 w-full bg-regal-blue-400 text-xl;
}
.formulate-input-element button {
#apply border-none;
}
.formulate-input-element--submit {
width: fit-content;
#apply py-1 px-4 bg-regal-blue-600 border-2 border-red-600 rounded-full tracking-wider;
}
.formulate-input-element input:focus,
.formulate-input-element select:focus {
outline: none;
}
.formulate-input-errors {
color: hsl(0, 100%, 40%);
}
</style>

Related

How to pass props dynamically in vue

I am trying to pass props to a router-link which is used to take me to the update or delete page. In order for me to update the right element, I need to pass the item's id as a prop to the component(dropdown menu) to dynamically render the update and delete pages.
Here is my dropdown component:
<template>
<div class="dropdown">
<button #click="toggleMenu">
<fa class="dropdown_icon" icon="fa-solid fa-arrow-down" />
</button>
<div v-if="showMenu" class="menu">
<div class="menu-item" #click="itemClicked">
<router-link :to="`/updateList/${id}`" class="list__link"
>Update</router-link
>
<br />
<router-link :to="`/deleteList/${id}`" class="list__link"
>Delete</router-link
>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DropdownList',
props: ['id'],
data() {
return {
showMenu: false,
};
},
methods: {
toggleMenu() {
this.showMenu = !this.showMenu;
},
itemClicked() {
this.toggleMenu();
},
},
};
</script>
<style scoped>
.dropdown_icon {
padding: 0.2rem;
color: #ffd700;
background: black;
margin-top: 15px;
transition: var(--transition);
border-radius: 0.2rem;
height: 17px;
}
.dropdown_icon:hover {
background: white;
color: black;
height: 17px;
}
.menu {
background: white;
padding-left: 2rem;
padding-right: 2rem;
border-radius: 1rem;
}
.list_plus {
padding: 0.5rem;
border: 1px solid gray;
border-radius: 1rem;
transition: var(--transition);
}
.list_plus:hover {
background: black;
color: #ffd700;
}
.createList {
text-decoration: none;
}
.list__link {
text-decoration: none;
color: black;
}
</style>
Here is my code for the part in which I am sending the element's id as a prop to the component:
div class="all__lists" v-for="(item, index) in items" :key="index">
<div class="list">
<div class="title">
<div class="title__options">
<h1 class="list_name">{{ item[0].list_name }}</h1>
<Dropdown :v-bind:id="`${item[0].list_id}`" />
<!-- V-menu -->
<!--menu ends-->
</div>
</div>
</div>
</div>
The Items object looks like:
But when I Try to access the update or delete page, the router redirects me to /updateList/undefined instead of /updateList/1 or something. Can anybody help me in fixing this?
Your problem is that you mixed the v-bind directive with its shorthand :.
You wrote :v-bind:id instead of v-bind:id (or :id).
With your code, you should be able to get the id by defining the props v-bind:id in the child. It will work since :v-bind:id will be converted as v-bind:v-bind:id.

Transition vue router

I want a transition in my VueJS 3 project between 2 pages. I have a button and when I click on it, it goes on a new page with a dynamic URL. I would like a transition here. I don't have any errors but there is no transition when I change the page. I don't know why. It's true that initially I didn't had a <router-view/> tag, I had to add it to make the transition, maybe it doesn't use the router-view when it is changing the page so doesn't see the transition.
Here my code :
<template>
<div class="p-grid">
(...)
<div class="p-col" v-if="infoItem.length === 0">
</div>
<div v-else>
<router-link
:to=" {
name:
'Detail',
params: {
id: infoItem.name,
subcategory: infoItem.subcategory,
name: infoItem.name,
},
}">
<Button icon="pi pi-search-plus"></Button>
</router-link>
<router-view v-slot="{ Component }">
<transition name="route" mode="out-in">
<component :is="Component"></component>
</transition>
</router-view>
</div>
</template>
<script>
(
...)
</script>
<style>
.p-grid {
margin: 0.5rem;
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
}
/* Route transition */
.route-enter-from {
opacity: 0;
transform: translateX(100px);
}
.route-enter-active {
transition: ass 0.3s ease-out;
}
.route-leave-to {
opacity: 0;
transform: translateX(-100px);
}
.route-leave-active {
transition: ass 0.3s ease-in;
}
</style>
Do you any idea why ?
Thanks a lot

Buefy Carousel Thumbnail Indicator show duplicated image (Vuejs)

I'm trying to create a carousel with vertical thumbnails, but the thumbnails are being duplicated. I only have 2 image URLs, but it's showing 4 thumbnails.
App.vue:
<template>
<div id="app">
<b-carousel
:indicator-inside="false"
class="is-hidden-mobile"
:pause-hover="false"
:pause-info="false"
>
<b-carousel-item v-for="(item, i) in imagess" :key="i">
<figure class="image">
<img :src="item.url">
</figure>
</b-carousel-item>
<span v-if="gallery" #click="switchGallery(false)" class="modal-close is-large"/>
<template slot="indicators" slot-scope="props">
<span class="al image">
<img v-for="(p,index) in imagess" :key="index" :src="p.url" :title="props.i">
</span>
</template>
</b-carousel>
</div>
</template>
<script>
export default {
name: "App",
components: {},
data() {
return {
bundledatas: null,
imagess: [
{
url:
"https://specials-images.forbesimg.com/imageserve/37645633/960x0.jpg?cropX1=445&cropX2=3910&cropY1=258&cropY2=2207"
},
{
url:
"https://www.sovereigngroup.com/wp-content/uploads/2018/12/HK-4.jpg"
}
]
};
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.is-active .al img {
filter: grayscale(0%);
}
.al img {
filter: grayscale(100%);
margin: 2px 0;
}
.carousel {
display: grid;
grid-template-columns: auto 25%;
align-items: center;
}
.carousel-indicator {
flex-direction: column;
}
.indicator-item {
margin-right: initial !important;
}
</style>
demo
I only want to display 2 thumbnails for (one for each image) like this:
The problem is your indicators slot is displaying all items of imagess when it should only be displaying the one specified in props.i, which is the current index shown in the carousel.
The solution is to lookup the item in imagess by the index in props.i, and set the img's source URL accordingly:
<template slot="indicators" slot-scope="props">
<span class="al image">
<!-- BEFORE: -->
<!-- <img v-for="(p,index) in imagess" :key="index" :src="p.url" :title="props.i"> -->
<img :src="imagess[props.i].url">
</span>
</template>
updated codesandbox

Validation focus and error on the label text and input border

I'm new to vue js and still trying to figure out how to do it in a correct way.
I have input validation, when it's empty and click outside the input, it shows an error or red color on the border and label input. When it's onfocus, click inside the input or typing text, the border and label text becomes blue.
I do this with javascript and it works. (code snippet below)
I tried using vue to do that, but when I click 1 input, the other input also become focus.
(code snippet below)
My question is it possible to code it using vue instead of vanila?
VUE
data: function() {
return {
focusBlue: true
}
}
computed: {
inputFocus: function(){
return{
focus_blue: this.focusBlue
}
}
.focus_blue{
border: 1px solid #4990e2 !important;
}
.test1 input {
background-color: transparent;
border: 1px solid #9b9b9b;
padding: 10px;
color: #ffffff;
}
.test1 input:focus {
outline: none;
}
.test1 {
display: flex;
flex-direction: column;
width: 48%;
margin-top: 25px;
}
.test2{
color: #9b9b9b;
font-size: 14px;
margin-bottom: 5px;
display: block;
}
<div class="test1">
<label class="test2">First Name *</label>
<input type="text" #click="focusBlue = !focusBlue" :class="inputFocus">
</div>
<div class="test1">
<label class="test2">First Name *</label>
<input type="text" #click="focusBlue = !focusBlue" :class="inputFocus">
</div>
<div class="test1">
<label class="test2">First Name *</label>
<input type="text" #click="focusBlue = !focusBlue" :class="inputFocus">
</div>
JAVASCRIPT
userInputValidation: function() {
const userInput = document.querySelectorAll(".inputJs");
const userLabel = document.querySelectorAll(".guestlist-form-label");
const textArea = document.querySelector(".test");
userInput.forEach(function(input, index) {
const labelInput = userLabel[index];
const errorClass = "has-error";
const blueClass = "has-blue";
input.addEventListener("blur", function() {
var hasError = input.value === "";
input.classList.toggle(errorClass, hasError);
labelInput.classList.toggle(errorClass, hasError);
labelInput.classList.remove(blueClass);
console.log("okay");
});
input.addEventListener("focus", function() {
input.classList.remove(errorClass);
labelInput.classList.remove(errorClass);
labelInput.classList.add(blueClass);
console.log("okay");
textArea.classList.add(blueClass);
});
});
},
.guestlist-form-wrapper-textarea {
width: 100%;
margin-top: 25px;
}
.guestlist-textarea {
background-color: transparent;
text-indent: 5px;
height: 50px;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
color: #ffffff;
}
.guestlist-form-label.has-blue {
color: #4990e2;
}
.guestlist-form-label.has-error {
color: #d04843;
}
.inputJs.has-error {
border: 1px solid #d04843;
}
.guestlist-form-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 62%;
}
.guestlist-form-wrapper-input {
display: flex;
flex-direction: column;
width: 48%;
margin-top: 25px;
}
.guestlist-form-label {
color: #9b9b9b;
font-size: 14px;
margin-bottom: 5px;
display: block;
}
.guestlist-form-wrapper-input input {
background-color: transparent;
border: 1px solid #9b9b9b;
padding: 10px;
color: #ffffff;
}
.guestlist-form-wrapper-input input:focus,
.guestlist-textarea:focus {
outline: none;
border: 1px solid #4990e2;
color: #4990e2;
-webkit-box-shadow: 0 0 10px 0 rgba(73, 144, 226, 0.2);
box-shadow: 0 0 10px 0 rgba(73, 144, 226, 0.4);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="guestlist-form-wrapper-input">
<label class="guestlist-form-label">First Name *</label>
<input type="text" class="inputJs">
</div>
<div class="guestlist-form-wrapper-input">
<label class="guestlist-form-label">Last Name *</label>
<input type="text" class="inputJs">
</div>
<div class="guestlist-form-wrapper-input">
<label class="guestlist-form-label">Email *</label>
<input type="email" class="inputJs">
</div>
<div class="guestlist-form-wrapper-input">
<label class="guestlist-form-label">Phone *</label>
<input type="tel" class="inputJs">
</div>
<div class="guestlist-form-wrapper-textarea">
<label class="guestlist-form-label test">Booking note *</label>
<textarea
class="guestlist-textarea inputJs"
placeholder="Type your message"
name="textarea"
id="textarea"
cols="30"
rows="10"
></textarea>
First of all you're using #click event in Vue but blur/focus in the vanilla js.
Clicking on the input several times will toggle focusBlue variable.
Then we have second problem that said variable focusBlue is shared between each input - it's a variable of the vue component that holds those inputs.
You could either store an id/name of the input that is currently selected and toggle class if necessary or (even better) extract those inputs to separate component - so they could be reused elsewhere and toggle logic would be contained within them
<template>
<div>
<input type="text" #focus="selectedInput = 'input1'" #blur="selectedInput = ''" :class="{ 'focus_blue': selectedInput === 'input1' }"/>
<input type="text" #focus="selectedInput = 'input2'" #blur="selectedInput = ''" :class="{ 'focus_blue': selectedInput === 'input2' }"/>
<input type="text" #focus="selectedInput = 'input3'" #blur="selectedInput = ''" :class="{ 'focus_blue': selectedInput === 'input3' }"/>
</div>
</template>
<script>
// ...
data() {
return {
selectedInput: ''
}
}
// ...
</script>
or as a separate component
// input-component
<template>
<div :class="cssClassNames">
<input
type="text"
#focus="focus"
#blur="blur"
:value="value"
#input="$emit('input', $event.target.value)"
/>
</div>
</template>
<script>
// ...
name: 'customInput',
props: ['value'],
data() {
return {
focused: ''
}
}
// ...
methods: {
focus() {
this.focused = true
},
blur() {
this.focused = false
}
}
// ...
computed: {
cssClassNames() {
return {
'focused': this.focused,
'has-error': !this.value, // or other classes
}
}
}
// ...
</script>
an then somewhere in another component
<customInput v-model="valueOfThisInput" />

How do you apply Vue Transitions when Changing CSS Class?

I can't get Vue to apply Transition animation effects when changing from one CSS class to another (using V-bind).
I've gone through the Vue documentation but none of the examples work for my use case. I basically want the DIV to transition by fading nicely from full screen to "regular size" by toggling.
Please see Fiddle at https://jsfiddle.net/luckman8/892ktedz/
`
<div v-bind:class="{'fullscreen':isFullScreen, 'regularSize':!isFullScreen}">
<button type="button" #click="toggle">
Toggle
</button>
<p>
{{isFullScreen}}
</p>
</div>
`
The CSS:
.fade-enter-active, .fade-leave-active {
transition: opacity 3s ease-out;
}
.fade-enter, .fade-leave-to {
opacity: 0.1;
}
.regularSize
{
width: "50%";
height: "50%";
background-color: "green";
}
.fullscreen
{
display: flex;
flex-direction: column;
position: fixed;
background-color:blue;
top:0;
left:0;
width: 100%;
height: 100%;
flex-basis:10%;
overflow-y:hidden;
}
The Vue code:
new Vue({
el: "#app",
data: {
isFullScreen:false
},
methods: {
toggle()
{
this.isFullScreen = !this.isFullScreen
}
}
})
Thank you in advance!
The <transition> effects will only work for elements that change their visibility. So for example by using v-if.
So you have two options.
Either add a v-if logic to your template.
For example: (a quick mock up. could be refactored to be cleaner)
<div id="app">
<button type="button" #click="toggle">
Toggle
</button>
<transition name="fade">
<div
v-if="isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>FULL SCREEN</p>
<button type="button" #click="toggle">
Toggle
</button>
</div>
</transition>
<transition name="fade">
<div
v-if="!isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>SMALL SCREEN</p>
</div>
</transition>
</div>
Create the transition effect purely with css.