BootstrapVue control columns number in form group - vue.js

I have a simple form group in BootstrapVue with a couple of input fields and select boxes which are added dynamically on a button click and I need to display another element (button, div, whatever) to the right of it so I can bind a click event to it to remove the field.
This is my code (taken from the BootstrapVue page).
<b-card bg-variant="light">
<b-form-group horizontal
label="Street:"
label-class="text-sm-right"
label-for="nestedStreet">
<b-form-input id="nestedStreet"></b-form-input>
<div>X</div> # This gets pushed down to the next line...I need it in-line
</b-form-group>
<b-form-group horizontal
label="City:"
label-class="text-sm-right"
label-for="nestedCity">
<b-form-input id="nestedCity"></b-form-input>
</b-form-group>
<b-form-group horizontal
label="State:"
label-class="text-sm-right"
label-for="nestedState">
<b-form-input id="nestedState"></b-form-input>
</b-form-group>
<b-form-group horizontal
label="Country:"
label-class="text-sm-right"
label-for="nestedCountry">
<b-form-input id="nestedCountry"></b-form-input>
</b-form-group>
</b-card>
I see that BootstrapVue automaticaly adds a class col-sm-9 to every row in the form-group that's why, if I add another div after it, it will be pushed down to the next line but I want it to appear in-line. Is it possible to set the number of columns in the form-group row?

I figured out that rewriting it using regular Bootstrap <div class="form-group"> tag can allow me to customize the input field class, so instead of using <b-form-group> I used <div class="form-group">.

Related

Vuejs Rebind an Html Select List

I have a data-grid.
When the user clicks the "edit" button for a row in the grid, the div which contains the grid is made invisible (using v-if) and another div which contains an update form for that item is made visible (also using v-if).
As an added complication, the "edit" form contains a selectlist. This is bound to an array, but the array to which it is bound varies, depending on which item is selected in the grid (the items in the grid are different kinds of things).
How do I get that selectlist to rebind each time an item in the grid is clicked on for edit.
I realise I could do this by making a component, but that to me is overkill.
Is perhaps a slot the answer? Not sure how to proceed.
This is the relevant code:
<b-row v-if="editClaimFormVisible" class="mt-6 justify-content-md-center">
<b-col cols="6">
<b-form #submit.prevent="editClaimSubmit">
<b-form-group label="Enter New Claim Value:">
<b-form-select v-model="selectedClaimForEdit.claimValue" :options="getClaimOptions()" value-field="id" text-field="name" required>
<template #first>
<b-form-select-option :value="null" disabled>-- Please select a claim --</b-form-select-option>
</template>
</b-form-select>
</b-form-group>
<b-form-group>
<b-button type="submit" variant="primary">Save</b-button>
</b-form-group>
</b-form>
</b-col>
</b-row>

Vuejs - How to submit only the visible elements in a single form (with Vuelidate)

I have a form which includes some hidden and visible elements inside of it and I want to submit some of the elements without validating the hidden ones. At the top of my form there are three radio buttons and they control my form elements. When radiobutton1 selected, some of my form elements become visible and when another radio button is selected, there are some other form elements are visible and some of them are hidden. My question is how am I going to submit my form elements if only they are visible? All of the inputs should be in a single form so I am not allowed to separate them into different forms or different components. What I need to do is when I click the submit button of my form, the form should only submit the visible elements, and it shouldn't send me any error because I left some of the inputs empty (the hidden ones).
I also use Vuedalite so I couldn't figure out how to handle this problem. All of the input fields in the form has the required rule but this rule should be active ONLY IF THEY ARE VISIBLE.
Here is a little code.
<form #submit.prevent="submitForm">
<!-- Content Section -->
<div v-show="showContent">
<!-- Name Field-->
<div>
<div>
<label>Name</label>
<input v-model="name" :class="{'is-invalid' : $v.networkname2GHz.$error }" type="text"/>
<small class="errorMessage" v-if="!$v.name.required && $v.name.$dirty">Name field is required.</small>
</div>
</div>
<!-- Surname -->
<!-- Content Section -->
<div v-show="showContent">
<!-- Surname Field-->
<div>
<div>
<label>Surname </label>
<input v-model="surname" :class="{'is-invalid' : $v.surname.$error }" type="text"/>
<small class="errorMessage" v-if="!$v.surname.required && $v.surname.$dirty">Surnamefield is required.</small>
</div>
</div>
<div show="showContent">
<button type="submit">Save</button>
</div>
</form>
What I want to do is when the user selects the Name radio button only the Name field of the form will be visible and Surname will be hidden, I've done that, no problem. But how do I submit only the name field when surname still empty and has the required rule?
You can use v-if instead of v-show.
The main difference between the two is that, v-if - Only renders the element to the DOM if the expression passes. v-show - Renders all elements to the DOM and then uses the CSS display property to hide elements if the expression fails.

Pass row.item.attribute value to a modal with Bootstrap Vuejs

I have a table where in the last column there is a button that pressing it pops-up a modal with some information and actions to do.
To this modal I want to pass a value from the table (from a specific cell of each row) but the modal shows always the cell value from the last row of the table (it is like it considers the whole table as one row).
To do some test I wrote the attribute to be appeared on the button title ,and so far it works well (to each button it appears the correct attribute of each row).
It seems that in the next level (inside the modal) there is a misunderstanding and whichever modal opens it presents always the cell value of the last row.
table
modal
<b-table
sticky-header
selectable
select-mode="single"
selected-variant="success"
w-auto
show-empty
small
stacked="md"
id="eventdataTable"
striped
hover
responsive
:items="items"
:fields="event_columns"
:per-page="perPage"
:current-page="currentPage"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:sort-direction="sortDirection"
:filter="filter"
:filterIncludedFields="filterOn"
#filtered="onFiltered"
>
<template v-slot:cell(nearby_venues)="row">
<div>
<b-button
variant="info"
class="text-center"
size="sm"
#click="show1 = true"
v-b-modal="'modal1'"
>Nearby Venues {{ row.item.api_id }}
</b-button>
<b-modal
id="modal1"
ok-variant="info"
v-model="show1"
size="sm"
title="Nearby Venues"
> {{ row.item.api_id }} *This appears correct*
<p align="left">Choose Venues close to</p>
<b-form-select
v-model="userdata.eventApiId"
class="mb-3"
>
<template slot="first">
<option :value="row.item.api_id">
{{ row.item.api_id }} *This appears wrong -the value of the column cell from the last row*
</option>
</template>
</b-form-select>
<label
class="mr-sm-3"
for="venue-category-selection"
></label>
<b-form-select
class="mb-2 mr-sm-2 mb-sm-0"
v-model="userdata.selectedVenueCategory"
:options="venue_categories"
value-field="id"
text-field="name"
id="venue-category-selection"
size="sm"
></b-form-select>
<hr width="300" align="left" />
<div>
<p align="left">Distance</p>
<label
class="mr-sm-3"
for="event-place-selection"
></label>
<b-form-input
v-model="userdata.distance"
placeholder="distance"
width="5px"
></b-form-input
>km.
<b-button
size="sm"
variant="success"
#click="VenuesFromSelectedEvent"
v-b-toggle.collapse-2
>
Click Here
</b-button>
</div>
</b-modal>
</div>
</template>
</table>
The problem here is that there is a loop in this component going through every row, rendering a new b-modal for each row. The problem is in this part of the code:
```
<b-form-select
v-model="userdata.eventApiId"
class="mb-3">
```
Each time a modal is rendered for a new row, it changes the userdata.eventApiId to the value for the current row. So the userdata.eventApiId will always end up being the api_id for the last row of the table.
One solution would be to change the code so that when the button is clicked, you change the userdata.eventApiId to the row.item.api_id.
I also wouldn't recommend putting the modal in the loop, as you would be creating a lot of hidden modals. I would just have one modal outside of the table that changes the value of userdata.

Aligning button and alert vertically in Bootstrap 4 + Vue

Using bootstrap-vue in my VueJS application I'd like to place a button and an alert next to each other in one row with both items aligned centered vertically. Although I used <b-row align-v="center"> this doesn't seem to work.
As you can see in this example on Codesandbox, the buttons are aligned but the alert is not.
How can I align all the items?
The b-alert works a bit other than the buttons, so you have to apply different CSS rules to achieve the same effect:
<b-container>
<b-row align-v="center">
<b-col cols="2">
<b-button variant="primary">Button 1</b-button>
</b-col>
<b-col cols="2">
<b-button variant="secondary">Button 2</b-button>
</b-col>
<b-col class="d-flex align-items-center">
<b-alert class="mb-0 w-100" show>An alert...</b-alert>
</b-col>
</b-row>
</b-container>
This will work.
aligns the items in the last b-col with the flex utility classes
remove the bottom margin (mb-0), so the item has nothing in the way to be positioned
– applies width: 100% (with w-100 class), so the alert doesn't shrink because of the d-flex of the parent; instead of this class, you could use flex-grow-1, so the v-alert takes up the available space.

Vue v-model not reactive with BS4 radio button group

I'm hoping I'm just missing something simple because I've been looking at this for too long, but I'm stumped.
I have a form with inputs bound to vuejs. I have a group of 2 radio buttons for selecting the "gender", and the binding is working perfectly. If I click on either of the radio buttons, I can see the data change in the vue component inspector.
But I'm trying to change the radio buttons to a Bootstrap 4 button group, and can't seem to get the v-model binding to work. No matter what I try, the gender_id in my vue data is not getting updated when I click either of the buttons in the button group.
The form input values are being fed in through vue component properties, but for simplicity, my data for the radio buttons/button group would look like this:
export default {
data() {
return {
genders: {
1: "Men's",
2: "Women's"
},
gender_id: {
type: Number,
default: null
}
}
}
}
Here is the code I have for the radio button version (which is working properly):
<div class="form-group">
<label>Gender:</label>
<div>
<div class="form-check form-check-inline" v-for="(gender, key) in genders" :key="key">
<input type="radio"
class="form-check-input"
name="gender_id"
:id="'gender_' + key"
:value="key"
v-model.number="gender_id">
<label class="form-check-label" :for="'gender_' + key">
{{ gender }}
</label>
</div>
</div>
</div>
Here is the button group version that is not properly binding to the gender_id data in vue.
<div class="form-group">
<label>Gender:</label>
<div>
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-secondary" v-for="(gender, key) in genders" :key="key">
<input type="radio"
class="btn-group-toggle"
name="gender_id"
:id="'gender_' + key"
:value="key"
autocomplete="off"
v-model.number="gender_id">
{{ gender }}
</label>
</div>
</div>
</div>
I've been using the following Boostrap 4 documentation to try to get this working.
https://getbootstrap.com/docs/4.0/components/buttons/#checkbox-and-radio-buttons
In the documentation for button groups they don't even include the value property of the radio inputs, whereas they do include it in the documentation for form radio buttons.
https://getbootstrap.com/docs/4.0/components/forms/#checkboxes-and-radios
Is this for simplicity or do button groups of radio buttons not even return the value of the checked button?
I see other threads stating that buttons groups are not meant to function as radio buttons, but if that's true for BS4, then why would Bootstrap have button groups with radio buttons as they do in their documentation referenced above? If you can't retrieve the checked state, then why not just use a <button> instead of <label><input type=radio></label>?
Any ideas as to what I'm doing wrong and/or not understanding correctly?
Thanks so much!
Thanks so much to #ebbishop for his helpful insights.
The issue was related to vue and bootstrap both trying to apply javascript to the buttons in the button group.
To get around this issue, it was as simple as removing data-toggle="buttons" from the button group. By removing the data-toggle attribute, the bootstrap js is not applied and vue can manage the button group.
Nothing is actually wrong your use of v-model here.
However: you must add the class "active" to the <label> that wraps each radio-button <input>.
See this fiddle for a working example.
Is that what you're after?