display in a v-for loop VUE.JS - javascript

I have a v-for loop in a Vue.js Vue page that creates hyperlinks and the code works fine but the placement is that each item is below the last. I would like to place the values in a horizonal line with commas between them if possible.
<div v-for="objGrant in obj.GrantListData" :key="objGrant.NCI_GrantList" >
<b><a class="nav-link" #click.prevent="load_NIH_Reporter(objGrant.GrantID)"
v-bind:href="''"
aria-label= 'Support' >{{ objGrant.GrantID }}</a></b>
</div>
Is it possible the way I'm doing it?

Try to set display: flex on your wrapper div:
new Vue({
el: '#demo',
data() {
return {
obj: {GrantListData: [{NCI_GrantList: 1, GrantID: 1}, {NCI_GrantList: 2, GrantID: 2}, {NCI_GrantList: 3, GrantID: 3}]}
}
}
})
.list {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo" class="list">
<div v-for="(objGrant, i) in obj.GrantListData" :key="objGrant.NCI_GrantList" >
<b>
<a class="nav-link" #click.prevent="load_NIH_Reporter(objGrant.GrantID)"
v-bind:href="''"
aria-label= 'Support' >
{{ objGrant.GrantID }}
</a>
</b>
<span v-if="i < obj.GrantListData.length - 1">,</span>
</div>
</div>

You can simply achieve that by using CSS property display with a value inline or inline-block.
Live Demo :
new Vue({
el: '#app',
data: {
obj: {
GrantListData: [{
NCI_GrantList: 1,
GrantID: 123
}, {
NCI_GrantList: 2,
GrantID: 456
}, {
NCI_GrantList: 3,
GrantID: 789
}]
}
}
})
div {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(objGrant, index) in obj.GrantListData" :key="objGrant.NCI_GrantList">
<b><a class="nav-link" v-bind:href="''">{{ objGrant.GrantID }}</a></b>
<span v-if="index < obj.GrantListData.length - 1">, </span>
</div>
</div>

Related

How to assign v-on dinamically with v-for

I have a code in Vue that creates the elements of a menu using a v-for, and each element must have a different method when it's clicked.
So far I have this:
<span v-for="(menuItem, index) in menuItems" :key="index">
<li>
<a id="listItem">
<i class="bx" :class="menuItem.icon || 'bx-square-rounded'" />
<span class="links_name" v-on:click=menuItem.click>{{ menuItem.name }}</span>
</a>
<span class="tooltip">{{
menuItem.tooltip || menuItem.name
}}</span>
</li>
</span>
How can I assign different funcions on the v-on?
You can make the listener function as a node in the object list.
Sample Implementation
const app = new Vue({
el: '#app',
data() {
return {
list: [{
name: 'lg',
age: 27,
onClick: function() {
console.log("First Item Clicked");
}
}, {
name: 'camile',
age: 27,
onClick: function() {
console.log("Second Item Clicked");
}
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list" :key="item.name">
{{item.name}} - {{item.age}}
<button #click="item.onClick()">
Click Me
</button>
</li>
</ul>
<input type="text" v-model="list[0].name">
</div>
</body>

How to bind style on-click in a loop

I've an array of objects (items) that can be incremented with other items, I show them by looping into the array.
see:
and I would like to high-light an item when I click on it (e.g. : another border-top-color), but I'm failing at targeting one specific element and applying a style without applying the style to the whole array. Any idea?
Template, I'm using vuedraggable, don't mind it:
<template #item="{ element }">
<div
class="item"
:key="element"
#click="
messageItemTitle(element.title);
messageItemID(element.id);
"
>
<div class="item-title">
{{ element.title }}
</div>
<div class="item-subType">
{{ element.type }}
</div>
</div>
</template>
The script : Well, none of what I've coded previously worked, so here's the data only :
data() {
return {
dragItems: dragItemsList, //15 items that I can clone into dropItems
dropItems: [], //Array where I can add the items from dragItems
};
},
You can conditionally apply class:
const app = Vue.createApp({
data() {
return {
items: [{id:1, title: 'aaa', type: 'type1'}, {id:2, title: 'bbb', type: 'type2'}, {id:3, title: 'ccc', type: 'type3'}],
selected: null
};
},
methods: {
message(el) {
this.selected = el.id
}
}
})
app.mount('#demo')
.item {
border: 3px solid transparent;
border-top-color: black;
}
.selected {
border-top-color: green;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="(element, i) in items" :key="i">
<!--<template #item="{ element }">-->
<div
class="item"
:class="selected === element.id && 'selected'"
:key="element"
#click="message(element)"
>
<div class="item-title">
{{ element.title }}
</div>
<div class="item-subType">
{{ element.type }}
</div>
</div>
<!--</template>-->
</div>
</div>

Change selected tab on click event

I'm new in Vuejs and I want to change the selected tab of nav on click event I trying using function but console throw an error:
vue.runtime.global.js:8392 Uncaught TypeError: _ctx.changeTab is not a
function
CodePen
What I want to do, is to on #click event run a function that change selected tab and show content depending on the selected tab in a single paragraph element
Code:
<template>
<div>
<div class="sm:hidden">
<label for="tabs" class="sr-only">Select a tab</label>
<select id="tabs" name="tabs" class="block w-full focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md">
<option v-for="tab in tabs" :key="tab.name" :selected="tab.current">{{ tab.name }}</option>
</select>
</div>
<div class="hidden sm:block">
<nav class="flex space-x-4" aria-label="Tabs" :class="bg-gray-600">
<a v-for="tab in tabs" #click="changeTab(tab)" :key="tab.name" :href="tab.href" :class="[tab.current ? 'bg-purple-700 text-white' : 'text-purple-700 hover:text-gray-700', 'px-12 py-2 font-medium text-sm rounded-full font-bold text-lg']" >
{{ tab.name }}
</a>
</nav>
</div>
</div>
</template>
<script>
const tabs = [
{ id: 1 , name: 'LOREM', href: '#test1', current: false },
{ id: 2, name: 'IPSUM', href: '#test2', current: false },
{ id: 3, name: 'PDF', href: '#test3', current: true },
]
export default {
setup() {
return {
tabs,
}
function changeTab(selectedTab){
let test = this.tabs.find(selectedTab.id);
console.log(test)
}
},
}
</script>
<style>
nav {
width: max-content;
display: flex;
gap: 20px;
background: #E5E5E5;
border-radius: 20px;
}
</style>
How can I achieve this? Regards
Move your array to setup function, make it reactive with ref or reactive:
const { ref } = Vue
const app = Vue.createApp({
setup() {
const tabs = ref([
{ id: 1 , name: 'LOREM', href: '#test1', current: false },
{ id: 2, name: 'IPSUM', href: '#test2', current: false },
{ id: 3, name: 'PDF', href: '#test3', current: true },
])
const changeTab = (selectedTab) => {
tabs.value.map(t => {
t.id === selectedTab.id ? t.current = true : t.current = false
});
}
return { tabs, changeTab }
},
})
app.mount('#demo')
nav {
width: max-content;
display: flex;
gap: 20px;
background: #E5E5E5;
border-radius: 20px;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.0.5/tailwind.min.css">
<div id="demo">
<div>
<div class="">
<nav class="flex space-x-4 bg-gray-600" aria-label="Tabs" >
<a v-for="tab in tabs" #click="changeTab(tab)" :key="tab.name" :href="tab.href" :class="[tab.current ? 'bg-purple-700 text-white' : 'text-purple-700 hover:text-gray-700', 'px-12 py-2 font-medium text-sm rounded-full font-bold text-lg']" >
{{ tab.name }}
</a>
</nav>
</div>
<div v-for="tab in tabs" #click="changeTab(tab)" :key="tab.name" :href="tab.href" class="px-12" :class="[tab.current || 'hidden']">
{{ tab.id }} - {{ tab.name }} - {{ tab.href }}
</div>
</div>
</div>

Vue.js use component in another

I have a component that I would like to use in another in order to make a navigation menu. I want separate the menu from links. How can I display data in a child component in another parent component? I use Vue.js CDN.
I am a newbie in using vue.js. Thank you for your help.
index.html
<div id="navbar"><navbar-div></navbar-div></div>
navbar.js:
Vue.component('navbar-content', {
props: ['name', 'link'],
template: '<a class="navbar-item" v-bind:href="link">{{ name }}</a>'
})
Vue.component('navbar-div', {
props: ['links'],
template: `
<nav class="navbar is-dark">
<div class="navbar-brand">[...]</div>
<div class="navbar-menu">
<nav class="navbar-start">
<navbar-content v-for="item in links"
v-bind:key="item.id"
v-bind:name="item.name"
v-bind:link="item.link">
</navbar-content>
</nav>
</div>
</nav>
`})
new Vue({
el: "#navbar",
data: {
links: [
{id: 1, name: "Item 1", link: "link1"},
{id: 2, name: "Item 2", link: "link2"}
],
}
})
In your HTML you have to bind the links to navbar-div; otherwise it's not going to receive the data as props
Vue.component('navbar-content', {
props: ['name', 'link'],
template: `
<a
class="navbar-item"
:href="link"
>
{{ name }}
</a>
`
})
Vue.component('navbar-div', {
props: ['links'],
template: `
<nav class="navbar is-dark">
<div class="navbar-brand">[...]</div>
<div class="navbar-menu">
<nav class="navbar-start">
<navbar-content
v-for="item in links"
:key="item.id"
:name="item.name"
:link="item.link"
/>
</nav>
</div>
</nav>
`
})
new Vue({
el: "#navbar",
data: {
links: [{
id: 1,
name: "Item 1",
link: "link1"
},
{
id: 2,
name: "Item 2",
link: "link2"
}
],
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="navbar">
<navbar-div :links="links"></navbar-div>
</div>

Laravel VueJS bind dynamic quantity to each input in a products list component

Trying to create a dynamic form with a list of each product from a db. The form has the following fields for each product: product title, product price, quantity and total price. My issue is in the fact that I'm not sure how to add a v-model field for each product quantity input, since the list is being pulled from a v-for of all of the products. Here is part of my ProductsListForm vue component template:
<div v-for="product in products" :key="product.id" class="flex form-group">
<div class="flex p-title">
<label :for="product.title">{{ product.title }}</label>
<small>{{ product.price }}$</small>
</div>
<div class="flex p-input">
<input class="input" type="number" :name="product.title" v-model="quantity">
</div>
<div class="flex p-total">
<span>Total: {{ product.price * quantity}}</span>
</div>
</div>
export default {
props: ['products'],
data() {
return {
quantity: 0,
}
},
methods: {}
}
So my question is how can I bind quantity to each individual product? Right now, it obviously changes whenever ANY of the input fields are updated...
Any help will be greatly appreciated!
Rather than using v-model, you could instead listen for the input events on each element.
new Vue({
el: '#app',
data: () => ({
cart: [],
products: [{
id: 1,
name: 'foo'
},
{
id: 2,
name: 'bar'
},
{
id: 3,
name: 'baz'
}
]
}),
methods: {
updateCart(event, product) {
const index = this.cart.findIndex(i => i.name === product.name)
const item = {
name: product.name,
quantity: event.target.value
}
if (index !== -1) {
this.cart.splice(index, 1, item)
} else {
this.cart.push(item)
}
}
}
})
ul,
li {
list-style: none;
}
#app {
display: flex;
flex-direction: row;
justify-content: space-around;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<h5>products</h5>
<ul>
<li v-for="product in products" :key="product.id">
<label>{{ product.name }}</label>
<input #input="updateCart($event, product)" min="0" type="number">
</li>
</ul>
</div>
<div>
<h5>cart</h5>
<ul v-if="cart.length">
<li v-for="item in cart" :key="item.id">
<p>{{ item.name }} {{ item.quantity }}</p>
</li>
</ul>
<p v-else>no items in cart</p>
</div>
</div>
For the quantity to be related to the product (entry of products) - you will have to pass it to the products or make it an array by itself.
<div v-for="product in products" :key="product.id" class="flex form-group">
<div class="flex p-title">
<label :for="product.title">{{ product.title }}</label>
<small>{{ product.price }}$</small>
</div>
<div class="flex p-input">
<input class="input" type="number" placeholder="1" :name="product.title" v-model="quantity[product.id]">
</div>
<div class="flex p-total">
<span>Total: {{ product.price * getProductQuantity(product) }}</span>
</div>
</div>
export default {
props: ['products'],
data() {
return {
quantity: [],
}
},
methods: {
getProductQuantity(product) {
return this.quantity[product.id] || 0;
}
}
}

Categories