vueJS hide element in dynamic table row - vue.js

I have a table that looks like this:
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="title()">Remove title</a></td>
</tr>
</tbody>
</table>
Now I wonder how I can toggle a jquery .hide() on the <p class="title">My title</p> when the remove title link is clicked on.
I dont want to use v-show since I am trying to understand how I can target elements within dynamic generated rows in vueJS.
The problem is that there are many rows in my table so every title tag must have a uniqe class and I dont understand how I can hide a specific title on dynamic generated rows

Can be done this way using v-show directive.
new Vue({
el: '.table',
data: {
rows: [
{ showTitle: true, job: 'A' },
{ showTitle: true, job: 'B' },
{ showTitle: true, job: 'C' }
]
}
});
<script src="https://unpkg.com/vue#2.5.2/dist/vue.min.js"></script>
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p v-show='row.showTitle' class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="row.showTitle = false">Remove title</a></td>
</tr>
</tbody>
</table>
Edit:
Here is jQuery version but as I already said this is a bad practice.
new Vue({
el: '.table',
data: {
rows: [
{ job: 'A' },
{ job: 'B' },
{ job: 'C' }
]
},
methods: {
hideTitle(index) {
$(this.$refs['title' + index]).hide();
}
}
});
<script src="https://unpkg.com/vue#2.5.2/dist/vue.min.js"></script>
<script src="https://unpkg.com/jquery#3.2.1/dist/jquery.min.js"></script>
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p class="title" :ref="'title' + index">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="hideTitle(index)">Remove title</a></td>
</tr>
</tbody>
</table>

Try this one. it works. using v-f and title model
template
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td v-if="title === false"><p class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="title()">Remove title</a></td>
</tr>
</tbody>
</table>
script
data () {
title:false,
},
methods: {
title(){
this.title= true
}
}

As others have mentioned, mixing jQuery and Vue is not the best idea. However, if you must, you can use the event.target that #flypan mentioned along with some jQuery selectors to get what you want.
I put together a JSFiddle using your HTML as an example of what can be done:
new Vue({
el: '#app',
data: {
rows: [
{ job: 'A' }, { job: 'B' }
]
},
methods: {
title: function() {
$title = $(event.target).parent().parent().find("p");
$($title).hide();
}
}
});
You would probably want to tighten the selector to find the "p", but this is just an example. Here's the working JSFiddle:
https://jsfiddle.net/psteele/p5Lpxj5a/

For conditionally displaying, you can use v-show directive,document link here :
v-show doucment.
Hope this can be helpful to you!

Related

In vuejs, quoting variables in HTML element attribute doesn't work

Here is the code:
<tr v-for="(item, index) in detail" :key="item.name" class="[[ item.name ]]">
<td>[[ index + 1 ]]</td>
<td>[[ item.name ]]</td>
The rendered HTML looks like this:
<tr class="[[ item.name ]]">
<td>1</td>
<td>Job</td>
</tr>
<tr class="[[ item.name ]]">
<td>2</td>
<td>Jesse</td>
</tr>
<tr class="[[ item.name ]]">
<td>3</td>
<td>Wazert</td>
</tr>
The class="[[ item.name ]]" just don't change. What I expect is:
<tr class="Job">
<td>1</td>
<td>Job</td>
</tr>
<tr class="Jesse">
<td>2</td>
<td>Jesse</td>
</tr>
<tr class="Wazert">
<td>3</td>
<td>Wazert</td>
</tr>
How should I fix it?
First thing Square bracket not worked in vue.js you need to use interpolation for binding the data dynamically.
So you need to use like For Example
HTML
<table border="1">
<tr v-for="(item, index) in detail" :key="item.name" :class="item.name">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
</tr>
</table>
JS
data: function () {
return {
detail: [{ name: "Job" }, { name: "Jesse" }, { name: "Wazert" }],
};
},
Here you can play with code
You need to use class-binding and interpolate the data:
new Vue({
el: "#app",
data: () => ({
detail: [ { name: "Job" }, { name: "Jesse" }, { name: "Wazert" } ]
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr v-for="(item, index) in detail" :key="item.name" :class="item.name">
<td>{{index + 1}}</td>
<td>{{item.name}}</td>
</tr>
</table>
</div>

how to build dynamic table with vue?

I tried to find the way build table from the following data property:
data(){
return {
headlist: [
{row: ID},
{row: Name},
{row: Title},
{row: Description },
{row: Actions }
],
}
Template code:
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Title</th>
<th>Description</th>
<th>Actions</th>
</tr>
Now tried to replace to :
<thead>
<tr v-repeat="headlist ">
<th>{{row}}</th>
</tr>
</thead>
Found example from https://012.vuejs.org/guide/list.html
What is wrong my code?
That's the documentation for the older version of VueJS. You shouldn't be referring to that. Also, you should be using the v-for directive:
<th v-for="(entry, i) in headlist" v-bind:key="i">
{{ entry.row }}
</th>
Proof-of-concept:
new Vue({
el: '#app',
data: function() {
return {
headlist: [{
row: 'ID'
},
{
row: 'Name'
},
{
row: 'Title'
},
{
row: 'Description'
},
{
row: 'Actions'
}
],
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table class="table table-bordered">
<thead>
<tr>
<th v-for="(entry, i) in headlist" v-bind:key="i">
{{ entry.row }}
</th>
</tr>
</thead>
</table>
</div>

How to add new line within copying existing line in Vuejs - Laravel project

Here is my code.
When click "Add New Line" button, adding a blank line fine.
But, I need to adding copy existing line data within new table line.
Please help me.
addMarkerLine(){
this.form.markeratios.push({
size:null,
ratio:0,
})
},
<form action="">
<table>
<thead>
<tr>
<th>SL.</th>
<th>Size</th>
<th>Ratio</th>
<th>Action</th>
</tr>`enter code here`
</thead>
<tbody>
<tr v-for="(markeratio , index) in form.markeratios ">
<td >{{index + 1}}</td>
<td ><input type="text" v-model="markeratio.size"></td>
<td ><input type="text" v-model="markeratio.ratio"></td>
<td><button>Copy This Line</button></td>
</tr>
</tbody>
<tfoot>
<tr>
<td><span #click="addMarkerLine">Add New Line</span></td>
</tr>
</tfoot>
</table>
</form>
If you want to copy the data into the next row, you just have to define a function copyRow that accepts an object data and when your Copy This Line button is clicked, pass the current object to copyRow function. In that function, just push the data to the form.markeratios.
<template>
...
<tr v-for="(markeratio , index) in form.markeratios ">
<td >{{index + 1}}</td>
<td ><input type="text" v-model="markeratio.size"></td>
<td ><input type="text" v-model="markeratio.ratio"></td>
<td><button #click="copyRow(markeratio)">Copy This Line</button></td>
</tr>
...
</template>
<script>
export default {
...
data: {
return {
form: {
markeratios: []
}
}
},
methods: {
copyRow(data) {
this.form.markeratios.push(data);
}
}
}
</script>

Can't add new item using v-model in Vue JS

I am learning Vue.
Now, I am trying to add data with the price and finally, it calculates total price:
Here is the HTML
<div id="app">
<form #submit.prevent="addItem">
<table border="1" cellpadding="10" width="300">
<tr>
<td colspan="2"><strong>Add New Item</strong></td>
</tr>
<tr>
<td>
<input type="text" name="" v-model="newItem" placeholder="Item Name">
</td>
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price">
</td>
</tr>
</table>
</form>
<br>
<table border="1" cellpadding="10" width="400">
<tr>
<th>Item Name</th>
<th>Item Price</th>
</tr>
<tr v-for="(item, index) in items" :key="index">
<td>{{ item.name }}</td>
<td><input type="number" name="" v-model="item.price"></td>
<td><button #click="removeItem(index)">X</button></td>
</tr>
<tr>
<td>Total</td>
<td><strong>{{ total }}</strong></td>
</tr>
</table>
</div>
Here is the Vue Instance:
new Vue({
el : '#app',
data : {
items: [
{ name: 'Rice', price : 12.60 },
{ name: 'Oil', price : 22.00 },
{ name: 'Mango', price : 32.50 },
{ name: 'Orange', price : 42.00 },
],
newItem : '',
newItemPrice : '',
},
computed: {
total() {
var total = 0;
this.items.forEach( item => {
total += parseFloat( item.price );
})
return total;
}
},
methods: {
addItem() {
this.items.push({
name: this.newItem,
price: 0
});
},
removeItem( index ) {
this.items.splice( index, 1 )
}
}
});
You can see it's by default showing item name and price. I want to add new item using the v-model called newItem But It's not adding the new item to the table
BUT
If I remove the Item Price column I mean this line:
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price">
</td>
then it's adding the new item perfectly :(
can you tell me what's wrong here?
See two issues with the fiddle:
There is no way to submit the form data
When pushing the price field was not added to the object
After fixing both of them it works well in this fiddle.
This happens because of browser implementation. As mentioned in W3C Specs:
When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.
But in case of multiple elements, the enter keypress does not trigger the form submit and thus you get this behaviour.
To resolve this you can simply use #keyup.enter.prevent="addItem" to listen to the enter keypress on each input and call the addItem() function like:
new Vue({
el: '#app',
data: {
items: [{name:"Rice",price:12.6},{name:"Oil",price:22},{name:"Mango",price:32.5},{name:"Orange",price:42}],
newItem: '',
newItemPrice: null,
},
computed: {
total() {
var total = 0;
this.items.forEach(item => {
total += parseFloat(item.price);
})
return total;
}
},
methods: {
addItem() {
this.items.push({
name: this.newItem,
price: 0
});
},
removeItem(index) {
this.items.splice(index, 1)
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<div id="app">
<form #submit.prevent="addItem">
<table border="1" cellpadding="10" width="300">
<tr>
<td colspan="2"><strong>Add New Item</strong></td>
</tr>
<tr>
<td>
<input type="text" name="" v-model="newItem" placeholder="Item Name"
#keyup.enter.prevent="addItem">
</td>
<td>
<input type="number" name="" v-model="newItemPrice" placeholder="Item Price"
#keyup.enter.prevent="addItem">
</td>
</tr>
</table>
</form>
<br>
<table border="1" cellpadding="10" width="400">
<tr>
<th>Item Name</th>
<th>Item Price</th>
</tr>
<tr v-for="(item, index) in items" :key="index">
<td>{{ item.name }}</td>
<td><input type="number" name="" v-model="item.price"></td>
<td><button #click="removeItem(index)">X</button></td>
</tr>
<tr>
<td>Total</td>
<td><strong>{{ total }}</strong></td>
</tr>
</table>
</div>
You should put a new line in your form, my suggestion is to put just above the close form tag </form>:
<input type="submit" value="add">
Another fix to do is in your methods addItem()
addItem() {
this.items.push({
name: this.newItem,
price: this.newItemPrice
});
}
Where it is the number 0 you should provide the this.newItemPrice to it work properly.

Data is not showing up in html

I am running into a issue with showing the data from my variable, itemListPrice. I have checked in the console and the data is populated into the itemListPrice, but its not showing up in my html, am I loading it all wrong?
Here is the markup
<div id="app2">
<div id="TableContainer" style="width:798px !important">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<td><label>Catalog Name</label></td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ currentCatalogName }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td><label>Item Name</label></td>
</tr>
</thead>
<tbody>
<tr>
<td> {{ itemPriceList.Name }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td colspan="2"><label>Item List</label></td>
</tr>
</thead>
<tbody>
<tr>
<td width="575px">${{ itemPriceList.ItemListPrice }}</td>
<td>${{ itemPriceList.ItemListPrice }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td colspan="3"><label>Item Features</label></td>
<td></td>
</tr>
</thead>
<tbody>
<template v-for="item in itemPriceList.ItemFeatures">
<tr v-if="item.FeatureQuantity != 0">
<td width="250px">{{ item.FeatureName }}</td>
<td>{{ item.FeatureQuantity }}</td>
</tr>
</template>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td><label>Item IAM</label></td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ itemPriceList.ItemIAM }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
and here is my code
new Vue({
el: '#app2',
beforeCreate: function () {
StartBusyIndicator("#ItemPriceListWindow");
},
created: function () {
this.GetItemDetails();
},
mounted: function () {
StopBusyIndicator("#ItemPriceListWindow");
},
data: {
itemPriceList: [],
orderItems: currentOrderItems,
currentCatalogName: currentCatalog,
priceList: null
},
methods: {
GetItemDetails: function () {
TryCatch(function() {
let result = GetItemPriceDetails();
this.itemPriceList = result;
priceList = result;
});
},
GetOrderItems: function () {
},
OptionPriceSplitter: function (optionprice) {
return TryCatch(function() {
let sentenceSplit = optionprice.split('& ');
let comp = '';
for (let i = 0; i < sentenceSplit.length; i++) {
comp += sentenceSplit[i] + '\n';
}
return sentenceSplit;
});
},
GlobalListPriceCalculation: function (globalgroupid) {
return TryCatch(function() {
let listPrice = 0.00;
let priceList = this.itemPriceList;
let result = priceList.GlobalListPrices.filter(function(item) {
if (item.GlobalGroupID == globalgroupid) {
listPrice = listPrice + item.Price;
}
});
if (listPrice == 0) {
listPrice = "";
} else {
listPrice = "$" + listPrice.toFixed(2);
}
return listPrice;
});
}
}
});
assuming TryCatch(cb) is something along the lines of
function TryCatch(cb){ let x = null; try { x = cb() } catch(e) {} return x; }
you loose 2 important things:
this (you could bind it via cb.call(this))
utterly usefull error messages
furher points:
I have checked in the console
checkout the excellent browser plugin for ff and chrome vue-devtools
itemPriceList = []
you initalize itemPriceList as array, use it as array item in itemPriceList, but also use it as object {{ itemPriceList.Name }} - what shall it be ?