On click check all checkbox in vue js - vue.js

I Need to check all dynamic checkbox with vue js anytime user will click button.
Eg: Click on and all checkbox will be selected/deselected
var Records = Vue.component('Records', {
template : `
<button v-on:click="selectAll()" class="btn btn-outline-primary">Select All</button>
<table class="table table-striped table-hover">
<template v-for="(col_name, key) in form_object_keys">
<tr>
<th scope="col"></th>
<th scope="col" v-for="(col, key) in col_name">{{ col }}</th>
</tr>
</template>
<template v-for="(ps, index) in form_object">
<tr>
<td>
<div class="form-check">
<input type="checkbox" :value="form_id" />
</div>
</td>
<td v-for="dato in ps">{{ dato }}</td>
</tr>
</template>
</table>
`,
data() {
return{
title: 'Component Title',
form_id: 10,
form_object: ['item1', 'item2', 'item3'],
form_object_keys: ['key1', 'key2', 'key3'],
selectAll(){
//
}
}
}
});
I've created "selectAll" function which will be engaged by click button

I would keep the selected state in the reactive data as well, and bind the checkbox with v-model: Check this
<script setup>
import { ref } from 'vue'
const form_objects = ref([
{name: "item1", selected: false},
{name: "item2", selected: false},
{name: "item3", selected: true},
{name: "item4", selected: false},
]);
const selectAll = () => {
form_objects.value.forEach((item) => {item.selected = true})
}
</script>
<template>
<button v-on:click="selectAll()">Select All</button>
<div v-for="item in form_objects">
{{item.name}}
<input type="checkbox" v-model="item.selected" />
</div>
</template>

Related

I'm having a render error in my nuxt page with a property that cannot be read

I'm trying to add rows to a table dynamically with a method in nuxt.js, but the prop that I have defined doesn't work...
I receive this error from the console:
Property or method "invoice_customer" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
I'm trying with this template:
<template>
<div>
<h3>Customers</h3>
<input type="text" v-model="search" placeholder="Search for names..." />
<table v-if="customers.length > 0">
<tr>
<th>name</th>
<th>address</th>
</tr>
<tr v-for="customer in customers" :key="customer.id">
<td>{{ customer.name }}</td>
<td>{{ customer.address }}</td>
</tr>
</table>
<div class="center">
<p>Customer</p>
<select v-if="customers.length > 0">
<option v-for="customer in customers" :key="customer.id">
{{ customer.name }}
</option>
</select>
</div>
<table v-if="invoice_customers.length > 0">
<tr>
<th>Id</th>
<th>Amount</th>
<th>Expire Date</th>
<th>Note</th>
</tr>
<tr
v-for="invoice_customers in invoice_customer"
:key="invoice_customers.id"
>
<td>
<input
type="number"
name=""
id=""
v-model="invoice_customer.amount"
/>
</td>
<td>
<b-form-datepicker
id="example-datepicker"
v-model="invoice_customer.expire_date"
class="mb-2"
></b-form-datepicker>
</td>
<td>
<input type="text" name="" id="" v-model="invoice_customer.note" />
</td>
</tr>
</table>
<b-button variant="outline-success" #click="addNewInstallment">+ Add New</b-button>
</div>
</template>
and this is my script:
<script>
export default {
name: "IndexPage",
data() {
return {
selected: "",
customers: [],
search: "",
invoice_customers: [{
id: 0,
amount: 0,
expire_date: "",
note: "",
}],
};
},
props: {
},
async mounted() {
const response = await this.$axios.$get("/api/customers");
this.customers = response.data;
return this.customers.filter((p) => {
// return true if the product should be visible
// in this example we just check if the search string
// is a substring of the product name (case insensitive)
return p.name.toLowerCase().indexOf(this.search.toLowerCase()) != -1;
});
},
methods: {
addNewInstallment() {
this.invoice_customers.push({
id: 0,
amount: 0,
expire_date: "",
note: "",
});
}
}
}
</script>
invoice customer is defined in v-for cycle
You inverted the order in your v-for, it should be
v-for="invoice_customer in invoice_customers"

Search input in dynamic table

I'm new to Vue.js, so thanks for the help!!
I'm trying to implement a Search input for each column that filters the results for the user
this is my HTML file:
<div id="table" >
<div class=" container jumbotron mt-3 ">
<enter-data :resources="resources" ></enter-data>
</div>
<div class=" container jumbotron mt-1 ">
<table-list :resources="resources" :heads="heads" ></table-list>
</div>
</div>
And this is my JS file:
Vue.component('table-list', {
props: ['resources', 'heads'],
data () {
return {
selected: [],
selectAll: true,
userIds: [],
searchQuery: ''
}
},
computed: {
filteredResources: function () {
if (this.searchQuery) {
return this.resources.filter(item => {
// return this.item.value.toLowerCase().includes(this.searchQuery.toLowerCase());
// return this.searchQuery.toLowerCase().split(' ').every(v => item.value.toLowerCase().includes(v))
return this.item.FName.startsWith(this.searchQuery)
// return item.indexOf(this.searchQuery)>= 0;
})
} else {
return this.resources
}
}
},
methods: {
sortTable: function (resource) {
this.resources.sort(function (a, b) {
if (a[resource.value] > b[resource.value]) {
return 1
} else if (a[resource.value] < b[resource.value]) {
return -1
}
return 0
})
}
},
template: `
<div class="w-100 text-center d-flex justify-content-center flex-wrap">
<div class="w-75">
<!-- <input type="text" placeholder="search.." v-modle="searchQuery" >-->
<table class="table table-striped">
<thead>
<tr>
<th>
<input type="checkbox">
</th>
<th v-for="resource in heads" class="cursor" #click="sortTable(resource)">
<div />
{{ resource.name }}
</th>
</tr>
</thead>
<tbody>
<tr>
<td />
<td />
<td>
<input v-mode="searchQuery" type="text">
</td>
<td>
<input type="text">
</td>
</tr>
<tr v-for="resource in filteredResources">
<td>
<input type="checkbox">
</td>
<td v-for="column in heads">
{{ resource[column.value] }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
`
})
var app = new Vue({
el: '#table',
data: {
resources: [
{ 'id': 0, 'FName': 'Setareh', 'LName': 'Pashapour', 'Extra': 'Alishah' },
{ 'id': 1, 'FName': 'Soheil', 'LName': 'Pashapour' },
{ 'id': 2, 'FName': 'Simin', 'LName': 'Hajizadeh' },
{ 'id': 3, 'FName': 'Nouyan', 'LName': 'Arman' },
{ 'id': 4, 'FName': 'Abed', 'LName': 'Hamrang' },
{ 'id': 5, 'FName': 'Navid', 'LName': 'Ahanj' }
],
heads: [{ name: '#', value: 'id' }, { name: 'First Name', value: 'FName' }, { name: 'Last Name', value: 'LName' }]
}
})
Unfortunately it doesn't work
searchQuery data doesn't have any impact to my filter computed and nothing happend if i type any thing on it
my Any suggestions?
You're using the wrong directive name for form input binding. Change from v-mode to v-model for below line.
<input v-mode="searchQuery" type="text">

How to get more then one class in vue

I'm trying to get more then one class to show depending on what happens. For example if the user clicks on complete then my list is sorted to all the completed items, but what I would also like is that if a user clicks the done button then that item is hidden.
I did try this
<tr v-for="item in filteredItems" :class="[filteredItems.value, hide:item.pending]">
but that didn't work.
Here is my code
<template>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-3">
<ul class="list-group">
<li class="list-group-item" #click="setFilter('incomplete')">Not Complete</li>
<li class="list-group-item" #click="setFilter('complete')">Completed</li>
</ul>
</div>
<div class="col-md-9">
<table class="table table-striped table-sm mt-2">
<thead>
<tr>
<th>Description</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr v-for="item in filteredItems" :class="filteredItems.value">
<td>
{{ item.title }}
</td>
<td>
<button type="button" class="btn btn-success btn-sm" #click="$set(item, 'pending', !item.pending)">Success</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
filter: 'all',
items: [{
id: '1',
title: 'Task 1',
value: "pending"
},
{
id: '2',
title: 'Task 2',
value: "complete"
},
{
id: '3',
title: 'Task 3',
value: "complete"
},
{
id: '4',
title: 'Task 4',
value: "pending"
}
],
pending: undefined
}
},
computed: {
filteredItems() {
if (this.filter === 'all') return this.items;
else return this.items.filter(item => item.value === this.filter);
}
},
methods: {
setFilter: function(filter) {
this.filter = filter;
},
setComplete: function(id){
// console.log('setComplete - '+id);
if(id)
{
// console.log(id);
}
}
}
}
</script>
<style>
.hide{
display: none;
}
</style>
You're very close. Use Object syntax instead of Array syntax in the inline binding.
<tr v-for="item in filteredItems" :class="{myClass: filteredItems.value, hide: item.pending}">
Documentation: https://v2.vuejs.org/v2/guide/class-and-style.html

Disable/Enable input for each item from a loop VueJS

I try to enable/disable each input from a loop. The problem is that my method it works just after refresh. After I modify something in code and save, then the input works.
<tr v-for="(item, index) in customer_names" :key="item.id">
<td>
<input :disabled="!item.disabled"
v-model="item.name"
type="text"
</td>
</tr>
<div class="edit_mode"
:class="{'display-none':!item.disabled}">
<i class="fa fa-save" #click="disableInput(index)" aria-hidden="true"></i>
</div>
<div class="edit_mode"
:class="{'display-none':item.disabled}">
<i class="fa fa-edit" #click="enableInput(index)" aria-hidden="true"></i>
</div>
props:['customer_names'],
data(){
return{
disabled: [],
}
}
enableInput(index){
console.log('enableInput',this.customer_names[index].disabled);
this.customer_names[index].disabled = false;
},
disableInput(index){
console.log('disabeInput',this.customer_names[index].disabled);
this.customer_names[index].disabled = true;
}
I didn't fully understand your problem. I deduced that you might want to enable or disable the text fields that you create from the data provided. If this is still not what you meant, correct your question by pasting more source code, and explain your problem in more detail.
Vue.component("custom", {
template: "#custom-template",
props: ["customer_names"],
methods: {
enableInput(item) {
item.disabled = false;
},
disableInput(item) {
item.disabled = true;
},
toggleInput(item) {
item.disabled = !item.disabled;
}
}
});
new Vue({
data() {
return {
items: [
{ name: "fus", disabled: false },
{ name: "ro", disabled: false },
{ name: "dah", disabled: true }
]
};
}
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<custom :customer_names="items" />
</div>
<script type="text/x-template" id="custom-template">
<table cellpadding=5>
<tr>
<th>Input</th>
<th>Version 1</th>
<th>Version 2</th>
</tr>
<tr v-for="item in customer_names" :key="item.id">
<td>
<input :disabled="item.disabled" v-model="item.name" type="text" />
</td>
<td>
<button #click="item.disabled = false">E</button>
<button #click="item.disabled = true">D</button>
<button #click="item.disabled = !item.disabled">T</button>
</td>
<td>
<button #click="enableInput(item)">E</button>
<button #click="disableInput(item)">D</button>
<button #click="toggleInput(item)">T</button>
</td>
</tr>
</table>
</script>

Setting a value to true for v-for generated radio buttons

The rows of a table are generated using a v-for loop over an array of objects in graphicState. I am trying to create a column of radio buttons. When a radio button is checked, this should set graphicState[index].selected to true.
This post is interesting, but how can I use it set graphicState[index].selected to true?
<form>
<div class="row">
<div class="col-md-12 " align="center">
<table class="table-striped" v-on:mouseleave="mouseleave()">
<thead>
<tr>
<th></th>
<th>Show</th>
<th>Select</th>
<th>Shape</th>
</tr>
</thead>
<tbody>
<tr v-for="(form, index) in graphicState" :key="index">
<td #click="removeDate(index)"><i class="far fa-trash-alt"></i></td>
<td>
<input type="checkbox" v-model="form.show">
</td>
<td>
<input type="radio" name="grp" id="grp" value="true" v-model="form.selected">
</td>
<td v-on:click="toggleShape(index)">
{{ form.shape }}
</td>
</tr>
</tbody>
</table>
<div v-for="(form, index) in graphicState " :key="index">
</div>
</div>
</div>
</form>
You can use #change event handler:
<input type="radio" name="grp" id="grp" value="true" v-model="form.selected" #change="onChange($event, index)">
then handle in method:
methods: {
onChange (event, index) {
this.graphicState[index].selected = event.target.value
this.graphicState = JSON.parse(JSON.stringify(this.graphicState))
}
}
The code you have already should set the graphicState[index].selected to true for the radio inputs, but the input values (and thus graphicState[index].selected through v-model) are never set to false, which is a problem if the user is allowed to change their mind to select a different input. This occurs because the radio input's change-event is only fired when the its checked property is set to a truthy value (upon selection).
One solution is to add a change-event handler that clears the .selected value for the non-selected inputs.
// template
<tr v-for="(form, index) in graphicState">
<input #change="onRadioChange(index)" ...>
</tr>
// script
onRadioChange(selectedIndex) {
this.graphicState
.filter((x,i) => i !== selectedIndex) // get non-selected inputs
.forEach(x => x.selected = false)
}
But there's still another problem if you're using HTMLFormElement's native submit. In the following template, when the v-model value is true, Vue sets the radio input's checked property to true, which tells the HTMLFormElement to use this particular input's value as the group value...
<input type="radio"
name="grp"
v-model="form.selected"
value="true">
All the radio inputs have the same value, so the receiver of the form data won't be able to tell which input is selected. To address this, assign a unique value to each input based on the iterator item. For example, you could use ID:
<input type="radio"
name="grp"
v-model="form.selected"
value="form.id">
new Vue({
el: '#app',
data() {
return {
graphicState: [
{id: 'A', selected: false, show: false},
{id: 'B', selected: false, show: false},
{id: 'C', selected: false, show: false},
]
}
},
methods: {
mouseleave() {},
removeDate() {},
toggleShape() {},
onRadioChange(selectedIndex) {
this.graphicState
.filter((x,i) => i !== selectedIndex)
.forEach(x => x.selected = false)
},
}
})
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<form method="post" action="//httpbin.org/post">
<div class="row">
<div class="col-md-12" align="center">
<table class="table-striped" v-on:mouseleave="mouseleave()">
<thead>
<tr>
<th></th>
<th>Show</th>
<th>Select</th>
<th>Shape</th>
</tr>
</thead>
<tbody>
<tr v-for="(form, index) in graphicState" :key="form.id">
<td #click="removeDate(index)"><i class="far fa-trash-alt"></i></td>
<td>
<input type="checkbox" v-model="form.show">
</td>
<td>
<input type="radio" name="grp" :value="form.id" v-model="form.selected" #change="onRadioChange(index)">
</td>
<td v-on:click="toggleShape(index)">
{{ form.shape }}
</td>
</tr>
</tbody>
</table>
<pre>{{graphicState}}</pre>
</div>
</div>
<button>Submit</button>
</form>
</div>