How to invoke client side validation on vue-multiselect component? - vue.js

I am using the vue-multiselect library like so:
in src/components/FeedbackForm.vue
<div>
<CustomerSelect :required="true" />
</div
Question: How can I make this select component required on the client-side? I thought I would be able to simply add an HTML5 attribute like so:
in src/components/CustomerSelect.vue
template section:
<multiselect
id="customer_last_name_input"
v-model="c_lastname_value"
:options="getActiveUserProfiles"
label="lastname"
track-by="uid"
:close-on-select="true"
#select="onSelect"
#remove="onRemove"
required <----------can't do this?
>
script section:
props: ['required']
Doing the above code does not invoke client-side validation in the browser like a regular HTML select element. Thanks for any help.

As for docs it accepts a allowEmptybool prop.
allowEmpty || Boolean || Allows to remove all selected values.
Otherwise one must be left selected.
so it would be
<multiselect
id="customer_last_name_input"
v-model="c_lastname_value"
:options="getActiveUserProfiles"
label="lastname"
track-by="uid"
:close-on-select="true"
#select="onSelect"
#remove="onRemove"
:allow-empty="required" <----------do this?
>

Related

Getting element (button) data attribute with vue3

I have the following html div. The {{ }} represent liquid syntax and it renders server side.
<div class="two columns">
<button
data-value='{{ value }}'
class="button-selection"
:class="selectionButtonClass($event)"
#click="selectionButton($event)"
>
<span class="text">{{ value }}</span>
</button>
</div>
In a vue 3 instance I have the following method in the same page.
selectionButtonClass(el) {
console.log('checking val');
console.log(el);
}
My goal is to set a conditional class in the selectionButton method but I can't get the element to get the data attribute. The above appears in the console log as undefined. However the #click does show the event obviously it's recognize the onclick but not the class method check.
$event is only available to event handlers. #click="selectionButton($event)" defines an inline event handler, while :class="selectionButtonClass($event)" is not an event handler.
To get the element, you need to add a ref attribute to the <button>:
<button
ref="selectionButton"
data-value='{{ value }}'
class="button-selection"
:class="selectionButtonClass($event)"
#click="selectionButton($event)"
>
And access it by this.$refs.selectionButton, assuming you are using the options API. However, the ref is available only after the component is mounted. Thus you need to handle the case where the ref is null.
More on template refs: https://vuejs.org/guide/essentials/template-refs.html
Since you are using server side rendering, I think it would be better to render the value as a parameter of the selectionButton function on the server side.

Assign index of v-for to id of created component

I am creating components in a loop in my vue app. However, I need those components to have an id value like "board-1" etc. using the index of the loop. (Just like I did it with v-bind:key="component-${block._uid}".)
How can I achieve this?
<div
class = "col-4"
v-for="(block, index) in layouts"
v-bind:key="`component-${block._uid}`"
>
<Board
id="`board-${block._uid}`"
class="droparea"
#dropped-component="$emit('dropped-component', $event, index)"
:acceptsDrop=true
draggable="true"
>
Layout {{index + 1}}
</Board>
</div>
You need to bind the value for JS code to get executed, otherwise you are attributing a string, not JS code.
:id="`board-${block._uid}`"
You can also use v-bind, actually : is just a shorthand
v-bind:id="`board-${block._uid}`"

Watching a dynamically rendered field in Laravel Nova Vue component

In Laravel Nova, action modals are rendered in Vue by retrieving a list of fields to display through a dynamic component. I have replaced the action modal with own custom component, but am struggling to achieve the effect I want without also extending the entire set of components for rendering form fields.
I have my CustomResourceIndex.vue, containing a conditionally loaded (via v-if) ActionModal.vue, in which the form fields are rendered like so:
<div class="action" v-for="field in action.fields" :key="field.attribute">
<component
:is="'form-' + field.component"
:resource-name="resourceName"
:field="field"
/>
</div>
where the actual form field component is chosen based on the field.component value.
Those form fields (which I ideally do not want to have to extend and edit) are rendered like so:
<template>
<default-field :field="field" :errors="errors">
<template slot="field">
<input
class="w-full form-control form-input form-input-bordered"
:id="field.attribute"
:dusk="field.attribute"
v-model="value"
v-bind="extraAttributes"
:disabled="isReadonly"
/>
</template>
</default-field>
</template>
I would like to watch the value of specific fields and run methods when they change. Unfortunately due to a lack of ref attribute on the input elements or access to the value that the form element is bound to, I'm not sure how I can accomplish that from within ActionModal.vue.
I am hoping that because I have access to the ids still, there is some potential way for me to emulate this behavior.
Many resources I've found on my own have told me that anything with an ID is accessible via this.$refs but that does not seem to be true. I can only see elements that have an explicitly declared ref attribute in this.$refs, so I am not sure if I've misunderstood something there.
I would recommend looking into VueJS watch property.
You can listen to function calls, value changes etc.
watch: {
'field.component': function(newVal, oldVal) {
console.log('value changed from ' + oldVal + ' to ' + newVal);
},
},
Are those components triggering events? Try looking into the events tab of the Vue DevTools to see if some events are triggered from the default-field component when you update the value.
My guess is that you could write something like:
<div class="action" v-for="field in action.fields" :key="field.attribute">
<component
:is="'form-' + field.component"
:resource-name="resourceName"
:field="field"
#input="doSomething($event)"
/>
</div>
The $event value being the new value of the field.
Hit me on the comments if you have more info on the behavior of the default form fields (Are their complete code accessible somewhere?).

Vuelidate validate a bootstrapvue / vue form field on click action

I'm creating a signup form which verifies if a login_id selected by the user is available on the server.
This form is on bootstrapvue.
<b-form #submit="onSubmit" v-if="show" #reset="onReset" >
<b-form-group
id="signupInputGroup0"
label="Login:"
label-for="exampleInput0"
description="Choose a unique login id"
valid-feedback="Great! Your login id is unique"
invalid-feedback="Login id already exists. Please pick another login.">
<b-form-input
id="signupInput0"
type="login"
v-model="form.login"
required
placeholder="Enter a unique login id"
/>
<b-button variant="success" #click="onCheckAvailability">Check Availability</b-button>
</b-form-group>
...
My question now is regarding the call to onCheckAvailability. This function is going to call an API and set the valid status to LoginId field.
Am actually considering vuelidate to create validations for all form fields. Customize my own validation method call isUniqueLogin
validations:{
form: {
login: {
required,
isUniqueLogin: this.onCheckAvailability(this.login)
}, ...
In such a case, how do we pass this validation on click back to the form?
I'm looking for a neat and elegant way of doing it.
And also OK to use something else that can do this well.
Note: This is not a submit click. It's a simple field validation on click.
Sometimes, using frameworks can be tedious if I don't understand the paradigms well.
Both <b-form-group> and <b-form-input> have a prop called state which accepts true if the value is valid, false for invalid, or null if not validated.
You would need to set this prop (on both <b-form-group> and <b-form-input>) to the result of the checkAvailability call.
Note that invalid-feedback and valid-feedback props are used on <b-form-group> not <b-form-input>
See https://bootstrap-vue.js.org/docs/components/form-group

Custom Placeholder Component React-Select

How can I set a custom placeholder element?
I'd like to add a search icon when the field is empty
Thanks.
TLDR; I just figured out that I can just simply pass a component
I guess I did not get that a node could be a component.
The documentation indicates:
placeholder: PropTypes.string || PropTypes.node
type placeholder = string | React.ReactNode
The following line comes from the source. As you see, it allows a component to be passed.
return !this.state.inputValue ? <div className="Select-placeholder">{this.props.placeholder}</div> : null;
So I can use
<Select placeholder={<div>Type to search</div>} />
<Select placeholder={<div>Type to search</div>} />
works