I am trying to use b-form-checkbox with b-table. Trying to retrieve the selected module Ids.
<b-table
id="module-table"
:items="list.modules"
:fields="fields"
:busy="isBusy">
<template slot="num" slot-scope="row">
{{ row.index + 1 }}
</template>
<template slot="checkbox" slot-scope="row">
<b-form-group>
<b-form-checkbox v-if="!isLoading" v-model="row.item.selected" #change="selection(row.item.moduleId)" variant="outline-secondary" class="mr-1">
</b-form-checkbox>
</b-form-group>
</template>
</b-table>
data: {
fields: [
{ key: 'checkbox', label: '', class: 'd-none d-lg-table-cell' },
{ key: 'num', label: 'Num', class: 'd-none d-lg-table-cell' },
],
selected: []
}
Though I am able to retrieve the selected module Ids but unable to delete them while switching the checkboxes. If anyone can provide an idea on how to track if the checkbox is selected (true) or not selected (false). Thanks in advance.
methods: {
selection(item) {
if (true)
app.selected.push(item);
else
app.selected = app.selected.map(x => x != item);
}
},
The checkbox values are already stored in list.modules[].selected via the v-model, so you could just use a computed prop to get the selected modules instead of using a separate selected array:
Remove the #change="selection(⋯)" from <b-form-checkbox>:
<!--
<b-form-checkbox
v-model="row.item.selected"
#change="selection(row.item.moduleId)" // remove
>
-->
<b-form-checkbox
v-model="row.item.selected"
>
Remove the selection method and selected data property, since they're no longer needed.
export default {
data() {
return {
// selected: [] // remove
}
},
methods: {
// selection() {⋯} // remove
}
}
Add a computed prop that filters list.modules[] for selected modules:
export default {
computed: {
selected() {
return this.list.modules.filter(module => module.selected)
},
},
}
demo
Related
I created a very simple table with bootstrap-vue where i can filter my data using the built-in filter.
The problem i have now is that i want to add another filter where i can input a number and get all the rows where value is higher than the specified number. I don't really know where to start with this, since i'm already using a filter. Can anyone suggest an approach i can take for thi? Any advice is appreciated.
<template>
<div class="overflow-auto">
<b-form-fieldset horizontal label="Filter" class="col-6">
<b-input v-model="filter" placeholder="Filter table.."></b-input>
</b-form-fieldset>
<b-table
id="my-table"
:filter="filter"
:fields="fields"
:items="items"
small
></b-table>
</div>
</template>
<script>
export default {
data() {
return {
filter: '',
fields: [{'key': 'asset', 'sortable': true}, {'key': 'value', 'sortable': false}, {'key': 'address', 'sortable': false}],
items: []
}
},
computed: {
rows() {
return this.items.length
}
},
}
</script>
If you want to keep the existing filter and add yours, you could create a computed property, for example prefilteredItems and use it in your template:
<template>
<!-- ... -->
<b-input v-model="minValue" placeholder="Minimum value..."></b-input>
<!-- ... -->
<b-table
:items="prefilteredItems"
></b-table>
</template>
<script>
export default {
data() {
return {
filter: '',
minValue: 0,
/* ... */
items: []
}
},
computed: {
prefilteredItems() {
return this.items.filter(({ value }) => value >= this.minValue);
},
rows() {
return this.prefilteredItems.length
}
},
}
</script>
i have code below in Vue js that shows Categories from API and whenever i click on any of them it add it to the array AddCategory and post it to API, also i've implemented button Removeall that whenever i click on it, it remove all the selected categories in array (it will empty the array) and it works fine. my problem is when i want to click again on the selected single category (in function remove below) it's not poping it up from array however it pushed it twice, any help?
<template>
<b-row class="categories-row">
<div
class="categories"
v-for="(category, index) in categories"
:key="index"
#click="Add(category._id, index)"
:class="[selectedIndex.includes(index) ? 'green' : 'gray']"
required
>
{{ category.category_name }}
</div>
</b-row>
</template>
export default {
data() {
return {
categories: [],
selectedIndex: [],
AddCategory: [],
posts: {
description: null,
questionTitle: null,
categories: null,
},
};
},
methods: {
Add(AddCategory, index) {
if (this.selectedIndex.includes(index))
this.Remove(index);
else
this.selectedIndex.push(index);
this.AddCategory.push(AddCategory);
},
Remove(index) { //not working
this.selectedIndex.splice(this.selectedIndex.indexOf(index),1);
},
RemoveAll() {
this.AddCategory = [];
this.selectedIndex.splice(this.AddCategory);
},}}
try this:
Remove(index) {
this.selectedIndex = this.selectedIndex.filter((item)=> item !== index) ;
}
Edited:
#sara97 maybe you need remove it from this.AddCategory too.
Edited:
#sara97 and because it runs "this.AddCategory.push(AddCategory);" everytime. use {} in if and else.
Add(AddCategory, index) {
if (this.selectedIndex.includes(index)) {
this.Remove(AddCategory,index);
}else{
this.selectedIndex.push(index);
this.AddCategory.push(AddCategory);}
},
Remove(AddCategory,index) {
this.selectedIndex = this.selectedIndex.filter((item)=> item !== index);
this.AddCategory = this.AddCategory.filter((item)=> item !== AddCategory)
},
I have code below in vue js and I wanted to update data the model by using AddCategory and it works fine, on the other hand, I wanted to post this to API Url using the post data below, but when I set v-model="posts.AddCategory" it didn't work, is there a way to do it?
<b-form-input
id="input"
type="text"
name="AddCategory"
v-model="AddCategory" //v-model="posts.AddCategory" didn't work
placeholder="categories"
required
/>
<div
class="categories"
v-for="(category, index) in categories"
:key="index"
#click="Add(index, AddCategory)"
>
<mark> {{ category.category_name }} </mark>
<script>
export default {
name: "postComponent",
components: {
Editor: PrismEditor,
},
data() {
return {
categories: [],
selectedIndex: null,
isediting: false,
AddCategory: "",
posts: {
title: null,
question: null,
code: require("../example.js").default /* eslint-enable */,
},
};
},
methods: {
Add(AddCategory, index) {
this.AddCategory = AddCategory;
this.selectedIndex = index;
this.isediting = true;
},
Your v-model=posts.AddCategory won't work as you are hitting one of the object caveats as defined in vue https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects.
What you can do is first in your Add method you could to so:
Add(category,index){
this.$set(this.post,'AddCategory',category);
....
}
I am using the <b-table> component from BootstrapVue and trying to customize field output by using a formatter callback function. The table data displays fine , but for some reason the callback function method branchName() is not being called and the value is not being formatted to the branch name instead of the branch id.
I set up a codesandbox to demonstrate the problem: code demo
The goal of the method is to return the name of the branch item. However, only the branch_id is being returned. In other words, the record row under the Branch table column should say ACME10 and not 10.
My file named App.vue:
<template>
<div id="app">
<b-table striped hover :items="userProfiles"></b-table>
</div>
</template>
<script>
export default {
data() {
return {
userProfiles: [
{
uid: "3",
branch: 10
},
{
uid: "1",
branch: 20
},
{
uid: "2",
branch: 13
}
],
branches: [
{
branch_id: 13,
branch: "ACME13"
},
{
branch_id: 10,
branch: "ACME10"
},
{
branch_id: 20,
branch: "ACME20"
}
],
fields: [
{
key: "branch",
formatter: "branchName"
}
]
};
},
methods: {
branchName(value) {
const name = this.branches[0].find(branch => value === branch.branch_id);
return name;
}
}
};
</script>
Thanks for your help!
To answer the OPs original question (why the formatter function was not being called):
In your App.vue file you are missing binding your fields definition array to the fields prop of <b-table>. Try this:
<template>
<div id="app">
<b-table striped hover :items="userProfiles" :fields="fields"></b-table>
</div>
</template>
If <b-table> isn't passed a field definition array, it will peek at the first row's item data and grab the field names that it finds, and then generates its own internal fields definition (just the field keys and humanized labels)
You should use slots to implement custom behavior like. For more information https://bootstrap-vue.js.org/docs/components/table#scoped-field-slots
Here is how you could implement your code
<template>
<div id="app">
<b-table striped hover :items="userProfiles">
<template slot="[uid]" slot-scope="data">{{ data.item.uid }}</template>
<template slot="[branch]" slot-scope="data">{{ branchName(data.item.branch) }}</template>
</b-table>
</div>
</template>
Method:
branchName(value) {
const branch = this.branches.find(branch => value === branch.branch_id);
if (branch) {
return branch.branch
}
return ""
}
try this in your template
<template v-slot:cell(name)="data">
<router-link :to="/route/${data.index}">
{{ data.value }}
</router-link>
I am using Vue-multiselect with Laravel.
I am using the multiselect component in my form to let the user select multiple countries. The component works fine but when I submit the form and I dd() it, it shows [object Object].
I can't get the value of the multiselect component. I have found similar questions but none of them worked for me.
Here is my code:
The ExampleComponent.vue file:
<template slot-scope="{ option }">
<div>
<label class="typo__label">Restricted country</label>
<multiselect
v-model="internalValue"
tag-placeholder="Add restricted country"
placeholder="Search or add a country"
label="name"
name="selectedcountries[]"
:options="options"
:multiple="true"
track-by="name"
:taggable="true"
#tag="addTag"
>
</multiselect>
<pre class="language-json"><code>{{ internalValue }}</code></pre>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
components: {
Multiselect
},
props: ['value'],
data () {
return {
internalValue: this.value,
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
}
},
watch: {
internalValue(v){
this.$emit('input', v);
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
},
}
</script>
Here is my register form:
<div id="select">
<example-component v-model="selectedValue"></example-component>
<input type="hidden" name="countriespost" :value="selectedValue">
</div>
<script>
const select = new Vue({
el: '#select',
data: {
selectedValue: null
},
});
</script>
When I submit the form, the countriespost shows me me this: [object Object] instead of the actual value.
It's because you are providing an array of objects as options property:
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
so the value emited on input is an object.
Try to change the options to following:
options: [ 'Hungary', 'USA', 'China' ]
If you pass an array of objects to the :options prop of the multiselect component, you should submit the form with javascript so you can extract the object ids or whatever you need on the backend and then send them through.
Add a method like this:
submit: function() {
let data = {
objectIds: _.map(this.selectedOptions, option => option.id), //lodash library used here
// whatever other data you need
}
axios.post('/form-submit-url', data).then(r => {
console.log(r);
});
}
Then trigger it with a #click.stop event on your submit button.