So i have an array like this in my component script
actions: [
{
name: 'detail',
icon: 'bzi-eye',
func: this.detailHandler()
},
{
name: 'edit',
icon: 'bzi-edit',
func: this.editHandler()
},
{
name: 'delete',
icon: 'bzi-phone',
func: this.deleteHandler()
}
]
and i pass that array and use the function on the child like this, is that possible or not?
<button
v-for="action in tableConfig.actions"
:key="action.name"
class="btn bg-transparent px-6 ml-2 mr-2"
#click="action.func()"
>
<i class="bzi" :class="action.icon"></i>
</button>
Related
My hunch is that there is some hydration mismatch where the FontAwesomeIcon was not rendered on the server (only the span) and then on the client both child nodes of the NuxtLink were rendered (the svg and the span), prompting Nuxt to render the span twice.
The console does not return an error, though.
Any thoughts on how to debug this?
This is the Vue component:
<template>
<ul v-if="routes.length > 0" class="col-span-2 flex flex-col">
<li v-for="(item, i) in routes" :key="item.name">
<NuxtLink :to="item.path" target="_blank">
<FontAwesomeIcon :icon="item.icon" class="mr-3" fixed-width />
<span>{{ item.title }}</span>
</NuxtLink>
</li>
</ul>
</template>
<script lang="ts">
export default defineComponent({
props: {
links: {
type: Array,
default: () => ["instagram", "facebook", "email"],
},
},
computed: {
routes() {
return [
{
name: "instagram",
path: "https://www.instagram.com/insta.name/",
title: "Instagram",
icon: ["fab", "instagram"],
},
{
name: "facebook",
path: "https://www.facebook.com/fb.name",
title: "Facebook",
icon: ["fab", "facebook"],
},
{
name: "email",
path: "mailto:hello#example.com",
title: "Email",
icon: ["fas", "envelope"],
},
].filter((e) => this.links.includes(e.name));
},
},
});
</script>
I am trying to remove item from my list , i am using js delete operator but it can't , here is the code
HTML :
<ol v-if="status">
<li v-for="(item, key) in items" :key="item.title">
{{ item.title }} - Type - {{ item.type }}
<input v-model="item.type" type="text" value="{{ item.type }}" style="margin-left: 2%;" />
<button #click="delete items[key]">Remove Items</button>
</li>
</ol>
JS :
const sample = {
data() {
return {
newItem: [
{title: "", type: ""}
],
subject: 'Vue.js',
items: [
{ title: 'Javascript', type: 'Native'},
{ title: 'Vue', type: 'Framework'},
{ title: 'React', type: 'Framework'},
{ title: 'Angular', type: 'Framework'},
],
item: 'Javascript',
status: 1
}
},
}
Vue.createApp(sample).mount('#app')
you need to declare a proper method for your #click event:
<button #click="deleteItem(key)">Remove Items</button>
then, in your vue, methods section, declare this function:
methods:{
deleteItem(key){
this.items.splice(key, 1)
},
},
your complete vue code will be this :
const sample = {
data() {
return {
newItem: [
{title: "", type: ""}
],
subject: 'Vue.js',
items: [
{ title: 'Javascript', type: 'Native'},
{ title: 'Vue', type: 'Framework'},
{ title: 'React', type: 'Framework'},
{ title: 'Angular', type: 'Framework'},
],
item: 'Javascript',
status: 1
}
},
methods:{
deleteItem(key){
this.items.splice(key, 1)
},
},
}
Vue.createApp(sample).mount('#app')
Hi In your #onclick u dont use correctly ur function u most to do something like this :
<ol v-if="status">
<li v-for="(item, key) in items" :key="item.title">
{{ item.title }} - Type - {{ item.type }}
<input v-model="item.type" type="text" value="{{ item.type }}" style="margin-left: 2%;" />
<button #click="delete(item)">Remove Items</button>
</li>
</ol>
And here, delete is a function for delete ur item in items like this function
delete(item){
this.items.splice(item.title, 1)
},
I've been following VueJS official documentation on passing data to child components with props; though I'm not working with a string template. I'm aware about what happens when your prop is camel case; you should write it as kebab case.
Nevertheless, this is not the case since it's all lowercase and won't work.
I'm using nuxt and I've separated my work into files, which are:
<template>
<div class="row">
<input type="text" name="" id="" placeholder="Write your question" v-model="text">
<select v-model="selectedField">
<option v-for="option in options" :key="option.id" :value="option.value">
{{ option.text }}
</option>
</select>
<button class="btn btn-sm btn-primary" #click="$emit('add-field')"
v-bind:class="{ disabled: ($parent.count <= 1 && $parent.count == identifier) }">
>{{identifier}}</button>
<button class="btn btn-sm btn-danger" #click="$emit('delete-field')">-</button>
</div>
Now for its JS file:
export default {
data () {
return {
options: [
{
id: 1,
value: 1,
text: "Radio"
},
{
id: 2,
value: 2,
text: "Rate"
},
{
id: 3,
value: 3,
text: "Text"
}
],
props: ['identifier'],
selectedField: 1,
text: "",
}
},
}
Now, for my parent component:
<template>
<div class="offset-md-3" id="qz">
<form-maker
v-for="item in questions" :key="item._id"
v-on:add-field="addField()"
v-on:delete-field="deleteField(item._id)"
v-bind:identifier="item._id" <<--What I want to set
ref="child"
></form-maker>
<button #click="saveForm" class="btn btn-large btn-success">SAVE</button>
</div>
</template>
Finally:
var vm = null;
export default {
layout: 'admin',
components: {
formMaker
},
data() {
return {
count: 1,
questions: [{
_id: 1//static
}]
}
},
}
What I'm trying to do is, to use the prop for some validations, nevertheless it throws the next error:
Property or method "identifier" 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.
Thank you.
Here is where you go wrong. Props should not be in data(). See the code snippet below
<script>
export default {
props: ['identifier'],
data() {
return {
options: [
{
id: 1,
value: 1,
text: "Radio"
},
{
id: 2,
value: 2,
text: "Rate"
},
{
id: 3,
value: 3,
text: "Text"
}
],
selectedField: 1,
text: "",
}
}
}
</script>
I am trying to add a button to my vuejs DataTable. I created a Button component and I can add it as a column in my DataTable, but I can't send it through props. I do not have full knowledge of vue, for sure I am doing something wrong.
Vue.component('edit-button', {
template: `
<button class="btn btn-xs btn-primary" #click="goToUpdatePage">Edit</button>
`,
props: ['data'],
methods: {
goToUpdatePage: function(){
alert(data)
}
}
});
export default {
data() {
return {
numeroPagina: 1,
tiposNatureza: [],
utisMoveis: [],
list: [],
filtros: {
dataInicial: new Date().toISOString().split('T')[0],
dataFinal: new Date().toISOString().split('T')[0],
selectedUtisMoveis: [],
selectedStatus: [],
selectedTipoNatureza: [],
selectedTipoPesquisa: ''
},
tabela: {
columns: [
{
// <a data-toggle="modal" data-target="#ExemploModalCentralizado">${row.DESCRICAO}</a>
label: 'Descrição', representedAs: function (row) {
if (row.DESCRICAO) return `<a data-toggle="modal" data-target="#ExemploModalCentralizado">${row.DESCRICAO}</a> <button onclick="alertMe('TESTE')">TESTE</button>`
else return '<b>Sem informação</b>'
}, interpolate: true
},
{
label: 'Quantidade', representedAs: function (row) {
return `<p><span class="label label-primary" style="font-size: 17px">${row.QTD}</span></p>`
}, interpolate: true
},
{
label: 'Action',
component: 'edit-button',
data: 'row',
component_data: {
path: 'contact',
action: 'update'
}
}
],
rows: []
}
}
}
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h2 v-if="quantidadeDeRegistros > 0">Foram encontrado(s) {{ quantidadeDeRegistros }}
resultado(s)</h2>
</div>
<div class="ibox-content no-padding" style="font-size: 15px">
<datatable :columns="tabela.columns" :data="tabela.rows"></datatable>
<datatable-pager v-model="numeroPagina" type="abbreviated" :per-page="8"></datatable-pager>
</div>
</div>
</div>
</div>
I need to create a button that takes the information from the selected row (row.DESCRIPTION) and sends it to a method, where I will do some dealing in a modal. Thank you very much in advance.
Try using this to reference the component scope.
alert(this.data)
And remove:
props: ['data'],
You do not want a passed in prop called data. You want the component's defined data property
I want create a component that it can to scale with a nested object structure using the QExpansionItem from Quasar Framework.
I made a recursive component to try achieve this but doesn't shows like i hope. The items are repeated in a wrong way and I don't know why.
I am using Quasar V1.0.5, the component that i used QexpansionItem
Here the menu object
[
{
name: '1',
icon: 'settings',
permission: 'configuration',
description: '1',
url: '',
children: [
{
name: '1.1',
permission: 'configuration',
url: '/insuranceTypes',
icon: 'add',
description: '1.1'
},
{
name: '1.2',
permission: 'configuration',
url: '/insuranceTypes2',
icon: 'phone',
description: '1.2'
}
]
}, {
name: '2',
icon: 'person',
permission: 'configuration',
url: 'contacts',
description: '2'
}
]
MenuComponent.vue where i call side-tree-menu component
<q-list
bordered
class="rounded-borders q-pt-md"
>
<side-tree-menu :menu="menu"></side-tree-menu>
</q-list>
SideTreeMenuComponent.vue
<template>
<div>
<q-expansion-item
expand-separator
:icon="item.icon"
:label="item.name"
:caption="item.description"
header-class="text-primary"
:key="item.name"
:to="item.url"
v-for="(item) in menu"
>
<template>
<side
v-for="(subitem) in item.children"
:key="subitem.name"
:menu="item.children"
>
</side>
</template>
</q-expansion-item>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'side',
props: ['menu', 'children'],
data () {
return {
isOpen: false,
algo: 0
}
},
mounted () {
console.log('menu', this.menu)
},
computed: {
...mapGetters('generals', ['can'])
}
}
</script>
The elements 1.1 and 1.2 are repeated and I don't know fix it
I got stuck at the same problem and did not find any solution online. I managed to get it working with the below approach. This could be helpful for someone in the future :)
I am adding here the 2 most important code files that will get this working. Rest of my setup is nothing more than what is created by the quasar create [project-name] CLI command.
When you create the project with the above command, you get the MainLayout.vue and EssentialLink.vue file. I have modified those to achieve the required result.
**My MainLayout.vue file - the template **
EssentialLink below is the component that renders the menu recursively using q-expansion-item inside the drawer on the main layout page.
<template>
<q-layout view="hHh Lpr lFf">
<q-header elevated>
<q-toolbar>
<q-btn flat dense round icon="menu" aria-label="Menu"
#click="leftDrawerOpen = !leftDrawerOpen" />
<q-toolbar-title>
{{appTitle}}
</q-toolbar-title>
<div>Release {{ appVersion }}</div>
</q-toolbar>
</q-header>
<q-drawer
v-model="leftDrawerOpen" show-if-above bordered
content-class="bg-grey-1">
<q-list>
<q-item-label
header
class="text-grey-8">
Essential Links
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link">
</EssentialLink>
</q-list>
</q-drawer>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
script section of MainLayout.vue file. Key properties to note - children and level.
<script>
import EssentialLink from 'components/EssentialLink.vue'
export default {
name: 'MainLayout',
components: {
EssentialLink
},
data () {
return {
appTitle: 'Project Name',appVersion: 'v0.1',leftDrawerOpen: false,
essentialLinks: [
{
title: 'Search', caption: 'quasar.dev', icon: 'school',
link: 'https://quasar.dev',
level: 0,
children: [{
title: 'Documents', caption: 'quasar.dev',icon: 'school',
link: 'https://quasar.dev',
level: 1,
children: [{
title: 'Search (level 3)',
caption: 'quasar.dev',
icon: 'school',
link: 'https://quasar.dev',
level: 2,
children: []
}]
}]
},
{
title: 'Github',caption: 'github.com/quasarframework',
icon: 'code',link: 'https://github.com/quasarframework',
level: 0,
children: [{
title: 'Github Level 2',caption: 'quasar.dev',icon: 'school',
link: 'https://quasar.dev',level: 1,
children: []
}]
},
{
title: 'Forum',caption: 'forum.quasar.dev',
icon: 'record_voice_over',link: 'https://forum.quasar.dev',
level: 0,
children: [{
title: 'Forum Level 2',caption: 'quasar.dev',icon: 'school',
link: 'https://quasar.dev',
level: 1,
children: []
}]
}
]
}
}
}
</script>
Finally the EssentialLink.vue component
The code below recursively calls itself when it encounters more than 1 item in its children property. The level property is used to indent the menus as you drill down.
<template>
<div>
<div v-if="children.length == 0">
<q-item clickable v-ripple :inset-level="level">
<q-item-section>{{title}}</q-item-section>
</q-item>
</div>
<div v-else>
<div v-if="children.length > 0">
<!-- {{children}} -->
<q-expansion-item
expand-separator
icon="mail"
:label="title"
:caption="caption"
:header-inset-level="level"
default-closed>
<EssentialLink
v-for="child in children"
:key="child"
v-bind="child">
</EssentialLink>
</q-expansion-item>
</div>
<div v-else>
<q-item clickable v-ripple :inset-level="level">
<q-item-section>{{title}}</q-item-section>
</q-item>
</div>
</div>
</div>
</template>
*script section of the EssentialLink.vue component
<script>
export default {
name: 'EssentialLink',
props: {
title: {
type: String,
required: true
},
caption: {
type: String,
default: ''
},
link: {
type: String,
default: '#'
},
icon: {
type: String,
default: ''
},
level: {
type: String,
default: ''
},
children: []
}
}
</script>
Final output looks like this (image)