Vue – A Weblog of Priyank Maniar https://priyank.rocks Articles on web development & mobile app development Fri, 30 Jun 2023 09:31:09 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 Learning about V-list, V-list-item-group https://priyank.rocks/learning-about-v-list-v-list-item-group/ Fri, 30 Jun 2023 09:00:33 +0000 https://priyank.rocks/?p=9493 So, as we know we can set a value at v-list-item and a model at v-list-item-group. This works great for most cases.

I once had a bit different setup where, inside the v-list-item, I had several elements, and in that order viz. v-list-item-title, v-hover, v-row, v-col, v-menu, v-list, and v-list-item.

Now, the problem was, the value of the main v-list-item-group model was set to a random value when the v-list item was clicked (inside the v-menu). The solution then I found was, I set the value to the v-list-item (inside the v-menu) to the expected value. That resolved the value issue.

The second issue that appeared was since the v-list-item of the v-menu now has a value, and it’s also a current/active value of the model, it was solved then by the following:

I put flat to v-list, so that the background styling disappears, next the icon color was a bit heavy, which was then manually set to grey, the expected colour, via primary attribute. Last was the font-weight which was set to the v-list-item and that solved it.

In the ui we had a listing of some items, which had options of edit and delete.

]]>
Validating image existence on the client side with JavaScript, Vue & Vuetify https://priyank.rocks/validating-image-existence-on-client-side-with-javascript-vue-vuetify/ Tue, 13 Jun 2023 05:28:37 +0000 https://priyank.rocks/?p=9484 Validating an image path on a client-side is slightly tricky. It is easy with
1
<v-img @error
for simple usage but for a more real-world or complex setup, where we want to programmatically check whether the image path is valid or not is slightly tricky.Ā 

1
2
3
<v-img v-if="!showIconFromCommon && !showInitials"
                       :src="getIconPath()" :title="appName" @error="setShowIconFromCommon"
                />

However, with the following function, life is easy. One thing to note though: it throws a browser error, if the image is found missing. I’m yet to look into if the error can be suppressed by wrapping a try/catch block.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// CHECK IF IMAGE EXISTS
        checkIfImageExists (url, callback) {
            const img = new Image()
            img.src = url

            if (img.complete) {
                callback(true)
            } else {
                img.onload = () => {
                    callback(true)
                }

                img.onerror = () => {
                    callback(false)
                }
            }
        },

Usage:

1
2
3
4
5
6
7
                self.checkIfImageExists(self.getIconPath(), (exists) => {
                    if (exists) {
                        self.showIconFromCommon = false
                        self.showInitials = false
                    } else {
}
                })
]]>
Vue 2 (and Vuetify): Allow only numeric characters for phone https://priyank.rocks/vue-2-and-vuetify-allow-only-numeric-characters-for-phone/ Tue, 17 Jan 2023 13:05:11 +0000 https://priyank.rocks/?p=9251 I used watch for this but there’s one small little tricky part.


1
2
3
4
5
6
7
8
9
phone: function (val) {

            let self = this;

            self.$nextTick(function () {
                self.phone = val.replace(/&#91;^\d.-]+/g, '');
            });

        },

That is, we need to put a $nextTick to make this work.

]]>
Vuetify: Working with v-dialog in a single file component (SFC) https://priyank.rocks/vuetify-working-with-v-dialog-in-a-single-file-component-sfc/ Mon, 23 May 2022 11:12:43 +0000 https://priyank.rocks/?p=9042 I often make all dialogs as a single file component (SFC). Then there are a couple of problems that I come across, but there are solutions to those so nothing to worry.

First is when rendering the component use a v-if. For props as well as the source of the dialog which makes the dialog appear and disappear. It helps solve an important issue.

1
2
3
4
<dialog-add-edit-device-name
            :params="addEditDeviceDialogParams"
            v-if="editUserNameParent && editUserNameCategoryParent && addEditDeviceDialog"
        ></dialog-add-edit-device-name>

When inside a component (SFC), VDialog (v-dialog) does not render mounted each time. Only the first time. We are having v-if (on the v-dialog model) here so that makes mounted run each time but there are more reasons to have v-if as well (but I don’t remember šŸ™ ). Otherwise we could also run into an issue where the dialog opens fine only once. This could happen if we are reading from props and assigning it to a data property inside mounted, since mounted runs only once and when clicked outside, if we do not make the data property false, it would not open the dialog again. Solution to this is mentioned below.

It is important for me to allow escape or outside click but that was resulting a bug with opening multiple dialogs.

For the following code please notice the

1
@keydown.esc
and
1
@click.outside
they both call the closing method which simply makes the dialog variable as false but for now we need to do this manually. Otherwise, it gets buggy.

1
2
3
4
5
6
7
    <v-dialog
        v-model="$props.params.addCategoryDialog"
        transition="dialog-bottom-transition"
        max-width="600px"
        @keydown.esc="closeAddCategoryDialog()"
        @click:outside="closeAddCategoryDialog()"
    ></v-dialog>

Please note the above learnings are in context of Vue 2 and not Vue 3.

]]>
All Learnings for v-dialog https://priyank.rocks/all-learnings-for-v-dialog/ Fri, 04 Mar 2022 08:06:25 +0000 https://priyank.rocks/?p=8937 V-Dialog fullscreen hiding behind WordPress Sidebar
1
2
3
4
<v-dialog v-model="editDialog" persistent="" max-width="800px" :retain-focus="false" fullscreen="" transition="dialog-bottom-transition" style="z-index:20001;">
<v-dialog>

</v-dialog>

The trick is to add the z-index to the v-dialog

]]>
[Solved] Vuetify V-Select Not Showing Placeholder/Label https://priyank.rocks/vuetify-v-select-not-showing-placeholder-label/ Sun, 09 Jan 2022 11:48:56 +0000 https://priyank.rocks/?p=8826 The problem: V-select was not showing the placeholder.

The solution is easy but nearly impossible to know at first.

1
<v-select v-model="topic" :items="topicForJS" label="Select Topic" outlined="" persistent-placeholder="" placeholder="Select Topic" :error-messages="topicErrors"></v-select>

The

1
persistent-placeholder
in combination with the
1
placeholder
does the trick.

V-select now displaying the placeholder text.

Perhaps this applies on v-autocomplete as well?

]]>
Vue V-for with number instead of Array https://priyank.rocks/vue-v-for-with-number-instead-of-array/ Sat, 06 Jun 2020 20:58:23 +0000 https://priyank.rocks/?p=6757 Yep that does it. item.score is a number not an Array.

1
2
3
<div v-for="index in parseInt(item.score)"
                                                   :key="index">
</div>
]]>
Vuelidate – How to …? https://priyank.rocks/vuelidate/ Sun, 09 Dec 2018 20:37:46 +0000 http://priyank.rocks/?p=262 This article contains all my learnings of the Vuelidate plugin. Should you find this helpful, please consider dropping a comment šŸ™‚

How to use perform a custom validation?


1
2
3
4
5
6
7
8
9
10
11
const validatePhoneNumber = (value) => {

    if (value) {
        value = value.replaceAll(/&#91;^0-9]/g, '');

        return value.length === 10;
    }

    return false;

};
1
2
3
 validations: {
        phone: {required, validatePhoneNumber}
    },

How to validate checkbox with Vuelidate (or perhaps even a radio button?)

1
        sameAs: sameAs( () =&gt; true )

Otherwise, the error is thrown first but if you check and uncheck again and submit the form again then the error won’t be thrown.

Source: https://github.com/vuelidate/vuelidate/issues/332

$v.days.$dirty && !$v.days.required $v.loan_purpose.$error $v.call_email_address.$invalid

How to use requiredIf?

1
2
3
4
5
6
7
8
9
kindOfVehicle: {
            required: requiredIf(function (nestedModel) {
                return this.currentStep === 1;
            })
        },

name: {
    required: requiredIf('document')
},

How to check for a field with vuelidate whether it is valid or invalid inside the vue instance?

1
this.$v.call_email_address.$invalid

Form dirty touch and validity check


1
2
3
4
var self = this;
self.$v.$touch();
if (!self.$v.$invalid) {
}

Bootstrap 4 input field validation example


1
2
3
4
5
6
7
8
9
10
11
&lt;div class="slide-ranger col-md-12"&gt;
    &lt;label for="amount" class="control-label sr-only"&gt;Loan Amount&lt;/label&gt;

    &lt;input type="text" id="range" name="range" class="form-control" v-model="range" :class="{'is-invalid': $v.range.$error, 'is-valid': (!$v.range.$error &amp;&amp; $v.range.$dirty)}" @keyUp="$v.range.$touch();"&gt;
    &lt;div class="invalid-feedback" :class="($v.range.$error &amp;&amp; $v.range.$dirty)"&gt;Please enter a valid loan amount
    &lt;/div&gt;

                            &lt;p id="slider-range-min"&gt;&lt;/p&gt;
                            &lt;span style="display: flex;justify-content: center;font-size: 10px;"&gt;* use the slider to select the desired loan amount or input manually&lt;/span&gt;

                        &lt;/div&gt;

Bootstrap 4 select / dropdown validation


1
2
3
4
5
6
7
8
9
10
&lt;div class="form-group col-md-6 mt30"&gt;
                            &lt;label class="control-label" for="loan_purpose"&gt;What is the purpose of loan?&lt;/label&gt;
                            &lt;select id="loan_purpose" name="loan_purpose" class="form-control" v-model="loan_purpose" :class="{'is-invalid': $v.loan_purpose.$error, 'is-valid': (!$v.loan_purpose.$error &amp;&amp; $v.loan_purpose.$dirty)}"
                                @change="$v.loan_purpose.$touch();"&gt;
                                &lt;option value=""&gt;Select purpose of loan&lt;/option&gt;
                                &lt;option value="Home Improvement/Renovation"&gt;Home Improvement/Renovation&lt;/option&gt;
                                &lt;option value="Bill Consolidation"&gt;Bill Consolidation&lt;/option&gt;
                                &lt;option value="Retail/Purchase"&gt;Retail/Purchase&lt;/option&gt;
                            &lt;/select&gt;
                        &lt;/div&gt;

Vuelidate Nested Validation

The validation for nested validation is slightly tricky. It involves the use of $each and the methods in the computed no longer work for us. Shortly we will discuss why. Another thing is writing the errors for the HTML part also gets trickier with the loop.

Despite all these problems, the right understanding will help us set things up pretty quickly.

First thing first!

You should know about $v.

In the Vue debugging panel, you can view elements inside $v and this will help you see the things under the hood and whats going on?

Setting up the rules in the validations block should be identical to what you have in the data block. Just when you start the array or the object part with the brace inside the array. Have an $each over there.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
data: {

    qualifications: [{
        name: '',
        document: ''
    }],

}
,

validations: {

    qualifications: {

        $each: {
            name: {
                required: requiredIf('document')
            }
        ,
            document: {
                required: requiredIf('name')
            }
        }

    }

}
,

methods: {

    qualificationNameErrors(i)
    {
        const errors = [];
        if (!this.$v.qualifications.$each[i].name.$dirty) return errors;
        !this.$v.qualifications.$each[i].name.required &amp;&amp; errors.push('This field is required');
        return errors
    }
,

Like this! Observe this carefully! doing this carefully will save you time.

Next,

The second part is to write the error display code and the most important part here is to introduce a parameter. The parameter here in an index, it helps track that the error is for which iteration and highlights only that specific element. One more thing to note here is computed properties will not work here well with the parameter. The fix is very simple. Move the method to methods.

I figured the following part by looking at $v carefully, hence $v should be observed carefully.

1
this.$v.qualifications.$each[i].name.required
1
2
3
4
5
6
7
8
9
10
11
<v-row style="border: 1px solid lightblue;border-radius: 4px;" v-for="(qualification, index) in qualifications">
                            <v-col cols="12" md="6" class="pa-3">

                                <v-text-field label="Qualification Name" filled="" v-model="qualification.name" :error-messages="qualificationNameErrors(index)"></v-text-field>

                            </v-col>

                            <v-col cols="12" md="6" class="pa-3">
                                <v-file-input label="Upload Qualification" accept="image/*, .pdf" :error-messages="qualificationDocumentErrors(index)" v-model="qualification.document"></v-file-input>
                            </v-col>
<v-row>

Simplify Errors with https://dobromir-hristov.github.io/vuelidate-error-extractor/

]]>
Does Vuelidate offer any emailIf or emailUnless like requiredIf or requiredUnless? https://priyank.rocks/does-vuelidate-offer-any-emailif-or-emailunless-like-requiredif-or-requiredunless/ Mon, 03 Dec 2018 18:17:37 +0000 http://priyank.rocks/?p=252 The answer is no but we still have a problem that we need to solve. What do we do now?

Well, the answer is we don’t need to worry about it. If the condition for required is not met, the email rule should not apply and it doesn’t. Form submits as you would expect (without any errors). However, if user types in the email anyway then Vuelidate expects it to be in a proper format.

Following is just fine.

1
2
3
4
5
6
validations: {
letter_email_address: {
    required: requiredUnless('isLetter'),
          email
    }
}
]]>