Why cannot I hide a div with v-if? - vue.js

Scenario: I have two options for a signup page. In the second one, I have a few more input elements and I only want to render that div when I click the second checkbox. For that, I wrote a v-if and it does not work properly.
(the project is in Vue)
<v-checkbox v-model="checkboxes" label="Bireysel Üyelik" value="checkbox-1"></v-checkbox>
<v-checkbox v-model="checkboxes" label="Kurumsal Üyelik" value="checkbox-2"></v-checkbox>
<div v-if="checkboxes === 'checkbox2'">
<v-text-field
name="cellPhone"
label="Cep Telefonu"
type="text"
key="cell-phone"
outlined
dense
required
>
</v-text-field>
</div>
data() {
return {
checkboxes: "",
}
}
The Html and JS files are as above. The data is dynamically changed in the Vue instance and there is no problem with that. The problem is with the conditional rendering mentioned above.

In your checkbox you bind a value of checkbox-2
<v-checkbox v-model="checkboxes" label="Kurumsal Üyelik" value="checkbox-2"></v-checkbox>
but then you look for checkbox2
<div v-if="checkboxes === 'checkbox2'">
<v-text-field
name="cellPhone"
label="Cep Telefonu"
type="text"
key="cell-phone"
outlined
dense
required
>
</v-text-field>
change it to:
<div v-if="checkboxes === 'checkbox-2'">
<v-text-field
name="cellPhone"
label="Cep Telefonu"
type="text"
key="cell-phone"
outlined
dense
required
>
</v-text-field>
and it will work :) .
Hope this helps!

Related

Is there a way to toggle visibility for multiple password fields with a dynamic form using vuetify vuejs?

I have a dynamic form that is constructed based off of json from the backend of input types, id, names, values, etc. One of my forms has two password fields that come from the backend. Is there a way to toggle visibility for multiple password fields on the same dynamic form? I'm having trouble figuring out how to do this to one at a time. Right now, the toggle icon switches both password fields on the screen.
<template>
<div class="pb-4" >
<template v-for="formField in formFields">
<v-row
:key="formField.key"
dense
align="center"
>
<v-col
md="3"
class="font-weight-bold text-right pr-10"
align-self="center"
>
{{formField.name}}
<span v-if="formField.required" class="small"> *</span>
</v-col>
<v-col
md="8"
align-self="center"
class="pl-3"
>
<v-text-field
v-if="formField.type === 'password'"
:id="formField.key"
:key="formField.key"
v-model="formField.value"
:append-icon="showPasswordIcon ? '$vuetify.icons.values.eye' : '$vuetify.icons.values.eyeSlash'"
:type="showPasswordIcon ? 'text' : 'password'"
:hint="getHintText(formField)"
:value="formField.name"
:required="formField.required"
:valid="(!formField.isValid) ? false : undefined"
dense
#input="inputHandler(formField)"
#blur="inputHandler(formField, false)"
#click:append="showPasswordIcon = !showPasswordIcon"
/>
<v-text-field
v-if="formField.type === 'text'"
:id="formField.key"
v-model="formField.value"
dense
:valid="(!formField.isValid) ? false : undefined"
#input="inputHandler(formField)"
#blur="inputHandler(formField, false)"
/>
<v-checkbox
v-if="formField.type === 'boolean'"
:id="formField.key"
v-model="formField.value"
class="mt-2"
/>
<v-text-field
v-if="formField.type === 'number'"
:id="formField.key"
v-model.number="formField.value"
dense
:valid="(!formField.isValid) ? false : undefined"
class="mb-0"
type="number"
#input="inputHandler(formField)"
#blur="inputHandler(formField, false)"
/>
</v-col>
</v-row>
</template>
</div>
</template>
Thank you so much for any tips on this!
Easiest solution might be to add an extra property to each element in the formFields, like visible, that tracks if a password should show its text. You can do that on API response and then insert it.
Then in your loop you can do
:type="formField.visible ? 'text' : 'password'"
This way, every formField is responsible for their own password visibility.
Next, you change
#click:append="showPasswordIcon = !showPasswordIcon"
to
#click:append="toggleShowPassword(formField.key)"
toggleShowPassword(key){
let formfield = this.formfields.find(x => x.key === key)
if(formfield){
formfield.visible = !formfield.visible
}
}
That should work!

vuetify: why the table is sorted whenever the user clicks into the input field

I have a vuetify datatable, the original solution is dynamic allocation of search text field using v-for for each of the column and then multi filter is implemented. following is my solution:
<template v-for="(header, i) in columns" v-slot:[`header.${header.value}`]="{ }">
{{ header.text }}
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</template>
The problem is whenever an user clicks on the text field of a particular column, the sorting function also runs at the same time. I have a miniature solution on the following pen which has the same behaviour. I tried to put one div after template tag but still the same. Kindly have a look at it. Any help would be appreciated.
Code Pen
Wrap the text field with a DIV and attach an empty handler to prevent the bubbling of CLICK events:
<template v-for="(header, i) in columns" v-slot:[`header.${header.value}`]="{ }">
{{ header.text }}
<div #click.stop>
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</div>
</template>

How to use v-item-group when using vue.components - Vuetify

I'm trying to create a group of selectable items using Vuetify.
Nevertheless, it is not working because inside the template I'm using a Vue.component called fm-card.
When you use a Vue.component you have to use #click.native instead of #click.
<v-item-group active-class="primary">
<v-container>
<v-row justify="center">
<v-col
class="fm-card-container"
cols="2"
v-for="item in items"
v-bind:key="item.id"
>
<v-item v-slot="{ active, toggle }">
<fm-card
#click.native="toggle;"
class="fm-card d-flex align-center"
:title="item.name"
:image="productImage(item.image)"
:imageHeight="95"
dark
height="200"
:color="active ? 'primary' : ''"
>
{{`hola soy el ${toggle}`}}
<v-scroll-y-transition>
<div v-if="active" class="text-h2 flex-grow-1 text-center">
Active
</div>
</v-scroll-y-transition>
</fm-card>
</v-item>
</v-col>
</v-row>
</v-container>
</v-item-group>
I have tried to use #click and #click.native but it seems that nothing is happening
First of all why don't you put your <fm-card> as an "real" component and reference it in your parent and pass all of your values you are using in there with it?
Like this
<fm-card :value1="value1" :value2="value2"/>
than you can put your complete code in this component - it's making your code much more clearer.
And than I think you don't need to use #click.native any more... #click should be enough, but than check that you have a semicolon after your toggle; - you have to delete this!
Than you can go to your methods and work with your click event like this:
methods: {
toggle() {
//your code in here
}
}
Hopefully this helps you out! Pls let me know!

Vuetify: v-text-field with outlined don't display the border

I use the Vuetify for Vuejs project. I add v-text-field elements to v-form with outlined property but it don't show the border. Thanks.
Code add Vuetify to project in main.js:
import Vuetify from 'vuetify/lib'
import 'vuetify/src/stylus/app.styl'
import 'vuetify/dist/vuetify.min.css'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
Vue.use(Vuetify, {
iconfont: 'md',
});
Use in the register form:
<v-form #submit.prevent="handleRegister" id="register-form" data-vv-scope="register-form">
<v-text-field outlined v-model="user.email" v-validate="'required|email'"
name="email" :error-messages="errors.collect('register-form.email')"
label="メールアドレス"
:class="{ 'is-invalid': submitted && errors.has('register-form.email')}">
</v-text-field>
<v-text-field v-model="user.password" v-validate="'required|min:8|max:20'"
:error-messages="errors.collect('register-form.password')"
:type="'password'" single-line outlined name="password"
label="パスワード"
:class="{ 'is-invalid': submitted && errors.has('register-form.password') }"
></v-text-field>
<v-text-field v-model="user.password_confirmation"
v-validate="'required|min:8|max:20'"
:error-messages="errors.collect('register-form.password_confirmation')"
label="パスワード確認" name="password_confirmation"
single-line outlined :type="'password'"
:class="{ 'is-invalid': submitted && errors.has('register-form.password_confirmation') }"
></v-text-field>
<v-text-field v-model="user.user_id" v-validate="'required|min:4|max:20'"
:error-messages="errors.collect('register-form.user_id')"
single-line outlined label="ユーザID" name="user_id"
:class="{ 'is-invalid': submitted && errors.has('register-form.user_id') }"
></v-text-field>
</v-form>
You use 1.5.5 vuetify version. You should try outline attribute instead of outlined. They changed it in v 2.0, and i think you've read v2 docs.

Is there is a better way to capture erros from Vuetify components?

I'm using the Vue.js library Vuetify to add a few text field components inside on a component that I create. In order to provide input validation I would like to capture the hasError property of the text field components. I know the path of the property is: this.$children[3]._computedWatchers.hasError.active. But I would like to know if there is another way to access theses properties. Maybe I'm missing something?
<template>
<div class="register">
<form>
<div>
<v-text-field name="new-user-email"
label="Email"
type="email"
single-line
required></v-text-field>
</div>
<div>
<v-text-field name="user-user-password"
label="Password"
type="password"
single-line
required>
</v-text-field>
</div>
<div>
<v-text-field name="new-user-password-confirmation"
label="Confirm Password"
type="password"
single-line
required>
</v-text-field>
</div>
<div #click="registerNewUser">
<v-btn>Register</v-btn>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'register-new-user',
data() {
return {
checked: false
};
},
methods: {
registerNewUser() {
console.log(this.$children[3]._computedWatchers.hasError.active)
console.log('Register a new user')
}
}
};
</script>
Add a ref attribute to the v-text-field component like this:
<v-text-field
ref="password-confirmation"
name="new-user-password-confirmation"
label="Confirm Password"
type="password"
single-line
required
></v-text-field>
Then you can reference the VueComponent instance of the Vuetify text field component (along with its properties and methods) like so:
methods: {
registerNewUser() {
console.log(this.$refs['password-confirmation'].hasError)
}
}
Here's documentation on refs.