I'm trying to display an image based on the concatenation of a fixed path and a property.
Do you know how I can do that?
<script>
export default {
props: {
id: String
}
}
</script>
<template>
<img src="#/assets/covers/{{id}}.jpg" width="240" height="180" />
<img src="'#/assets/covers/' + id + '.jpg'" width="240" height="180" />
<img src="`#/assets/covers/${id}.jpg`" width="240" height="180" />
<h1>#/assets/covers/{{id}}.jpg</h1>
</template>
I tried these 3 solutions but none are working. The h1 is displaying what I want though.
I even tried this:
<script>
export default {
props: {
id: String
},
data() {
return {
url: "#/assets/covers/" + this.id + ".jpg"
}
}
}
</script>
<template>
<img src="#/assets/covers/title.jpg" width="240" height="180" />
<img src=url width="240" height="180" />
<h1>#/assets/covers/title.jpg</h1>
<h1>{{url}}</h1>
</template>
The two h1 displays the exact same text, but only the first image is showing, not the second one.
Here I've described how to use images in vue3. Probably it could help you.
how to use img in vue3
I'm trying to save data with VueJS to a Go backend API.
When I click submit, the data is saved twice. I've tried to prevent this but something is missing.
I've tested the endpoint with Postman and it's saving normally.
Here is the component:
<template>
<div class="row">
<form #submit.prevent="PostDominio">
<hr />
<label id="lbldom">Dominio </label>
<input v-model="form.Titulo" type="text" />
<button
id="sendom"
class="btn btn-outline-primary btn-sm shadow-sm p-1 mb-1"
#click="PostDominio"
>
Gravar
</button>
<hr />
</form>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
form: {
Titulo: '',
},
}
},
methods: {
PostDominio() {
axios
.post('http://localhost:3000/dominios', this.form)
.bind(this)
.catch((error) => {
console.log(error)
})
},
},
}
</script>
I added e.preventDefault to the PostDominio(e) function and it solved my issue!
I'm fairly new to Vue and I'm trying to pass data from a component to a view. I'm not sure if I'm using props right. I have a dialog and when I save, I want to insert the data to the database. I also want to reuse the addCustomer() function that's why I didn't place the function in the component.
pages/customers.vue
<template>
<div>
<div class="items-center justify-between md:flex">
<Heading
title="Customers"
desc="The list of customers or companies you work with."
/>
<button #click="openModal" class="btn-primary">Add New Customer</button>
</div>
<CustomerList class="mt-4" :customers="customers" />
</div>
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
:add-customer="addCustomer"
/>
</template>
<script setup>
const client = useSupabaseClient();
const name = ref("");
const address = ref("");
const email = ref("");
const isOpen = ref(false);
function closeModal() {
isOpen.value = false;
}
function openModal() {
isOpen.value = true;
}
const { data: customers } = await useAsyncData("customers", async () => {
const { data } = await client.from("customers").select("*");
return data;
});
async function addCustomer() {
if (name.value == "" || address.value == "" || email.value == "") return;
const { data } = await client.from("customers").upsert({
name: name.value,
address: address.value,
email: email.value,
});
customers.value.push(data[0]);
name.value = "";
address.value = "";
email.value = "";
closeModal();
}
</script>
components/customer/Dialog.vue
<template>
<Dialog as="div" #close="closeModal" class="relative z-10">
<input type="text" id="name" v-model="name" />
<input type="text" id="address" v-model="address" />
<input type="email" id="email" v-model="email" />
<button type="button" #click="addCustomer">Save</button>
<button type="button" #click="closeModal">Cancel</button>
</Dialog>
</template>
<script setup>
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
</script>
EDIT: The Cancel button in the Dialog works while Save button doesn't.
You cannot bind props directly to the v-model directive, in your case you've to use Multiple v-model bindings
<template>
<Dialog as="div" #close="closeModal" class="relative z-10">
<input type="text" id="name" :value="name" #input="$emit('update:name', $event.target.value)"/>
<input type="text" id="address" :value="adress" #input="$emit('update:address', $event.target.value)" />
<input type="email" id="email" :value="email" #input="$emit('update:email', $event.target.value)" />
<button type="button" #click="$emit('add-customer')">Save</button>
<button type="button" #click="closeModal">Cancel</button>
</Dialog>
</template>
<script setup>
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
defineEmits(['update:name', 'update:email','update:address','add-customer'])
</script>
in parent component :
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
v-model:name="name"
v-model:address="address"
v-model:email="email"
#add-customer="addCustomer"
/>
As addCustomer method is available in parent. What you can do is that emit an event on Save button click from the dialog component and then capture the event in parent and invoke addCustomer method.
I just created a below code snippet with Vue 2.* just for your understanding purpose.
Vue.component('customerdialog', {
data() {
return {
customerDetailObj: {}
}
},
props: ['name', 'address', 'email'],
mounted() {
this.customerDetailObj = {
name: this.name,
address: this.address,
email: this.email
}
},
template: `<div><input type="text" id="name" v-model="customerDetailObj.name" />
<input type="text" id="address" v-model="customerDetailObj.address" />
<input type="email" id="email" v-model="customerDetailObj.email" />
<button type="button" #click="$emit('add-customer', customerDetailObj)">Save</button></div>`
});
var app = new Vue({
el: '#app',
data: {
name: 'Alpha',
address: 'Street 1',
email: 'alpha#testmail.com',
customerList: []
},
methods: {
addCustomer(customerObj) {
// Created user details
this.customerList.push(customerObj);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<CustomerDialog :name="name"
:address="address"
:email="email" #add-customer="addCustomer($event)"></CustomerDialog>
<pre>{{ customerList }}</pre>
</div>
You can defineEmits
<script setup>
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from "#headlessui/vue";
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
let emit = defineEmits(["add"])
</script>
Or better with typescript:
<script lang="ts" setup>
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from "#headlessui/vue";
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
let emit = defineEmits<{ (name: "add"): void }>()
</script>
Now you can use it in your button:
<button
type="button"
class="inline-flex justify-center px-4 py-2 text-sm font-medium text-red-900 bg-red-100 border border-transparent rounded-md hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2"
#click="emit('add')"
>
Save
</button>
Now you can listen to this add event and trigger your addCustomer function
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
#add="addCustomer"
/>
You'll want to use event emitters:
In the dialog:
<button #click="$emit('addCustomer')">save</button>
In customers.vue:
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
#add-customer="addCustomer"
/>
I have the following component, I would like to emit a second value isDeleted to the parent:
<template>
<div class="flex items-center">
<button class="btn my-auto inset-y-0 ml-1 mr-3"
:class="isDeleted ? 'btn-danger' : 'btn-secondary'"
#click="switchMode"
>
<Icon name="Trash" class="w-4 h-4" />
</button>
<div class="w-56 relative text-slate-500 mr-2">
<input
id="tabulator-html-filter-value"
name="search"
type="text"
autocomplete="off"
class="form-control w-56 box pr-10"
aria-label="default input example"
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
placeholder="Search..."
/>
<Icon name="Search" class="w-4 h-4 absolute my-auto inset-y-0 mr-3 right-0"/>
</div>
<button
id="tabulator-html-filter-reset"
type="button"
class="btn btn-secondary w-full sm:w-16 mt-2 sm:mt-0 sm:ml-1"
#click="$emit('reset')"
>
Reset
</button>
</div>
</template>
<script>
import Dropdown from '#/components/Dropdown/Dropdown'
import Icon from '#/components/Icons/Icons'
export default {
components: {
Dropdown,
Icon
},
props: {
modelValue: String,
maxWidth: {
type: Number,
default: 300,
},
},
data() {
return {
isDeleted: null,
}
},
emits: ['update:modelValue', 'reset'],
methods: {
switchMode() {
this.isDeleted = this.isDeleted ? null : 'only';
console.log('1'+ this.isDeleted);
}
}
}
</script>
The parent has the following code:
<search-filter v-model="form.search" class="mr-4 w-full max-w-md" #reset="reset" />
I tried following this example: https://dev.to/codybontecou/vuejs-custom-event-emit-multiple-values-221b to add emit the second value isDeleted without success.
Thanks
In child
<button
id="tabulator-html-filter-reset"
type="button"
class="btn btn-secondary w-full sm:w-16 mt-2 sm:mt-0 sm:ml-1"
#click="$emit('reset', isDeleted /* <---- Pass your value */)"
>
In parent
<search-filter
v-model="form.search"
class="mr-4 w-full max-w-md"
#reset="reset($event /* <---- Here got your value */)"
/>
const reset = (isDeleted) =>
{
console.log(isDeleted)
}
I have a button that should toggle and also call a method. How do I achieve this? Seems like it can be only one or the other.
new Vue({
el: "#app",
data: {
iExist:false,
iDoNotExist: true,
},
methods: {
iSignedUpforThis: function(){
console.log("step X");
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p v-show="iExist"> i EXISTS </p>
<p v-show="iDoNotExist">
<strong> You are not found: </strong>
<form >
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
</form>
<BUTTON v-on:click="iExists = iDoNotExist">
TOGGLE MY EXISTENCE
</BUTTON>
</div>
Move
iExists = iDoNotExist to a method:
methods: {
iSignedUpforThis: function(){
this.iExist = this.iDoNotExist
console.log("step X");
}
}
<button v-on:click="iSignedUpForThis">
TOGGLE MY EXISTENCE
</button>
First off to accomplish your desired result you need only one Boolean variable. Then in your method just switch between true and false. Also you have an invalid markup - there is closing tap p but no closing. That's why your example does not work.
Notice: it's bad idea to nest form tag inside p tag, so use div instead. It's considered a good practice to associate your input with it's label using label tag. Also there is shortcut for v-on:click - #click. data should be an function that returns an object, this will prevent . multiple instance to share the same object.
If you follow above recommendations you will make your code much clear and bug-less.
new Vue({
el: '#app',
data: {
isExist: false,
},
methods: {
method() {
this.isExist = !this.isExist
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-show="isExist">I exist</div>
<div v-show="!isExist">
<strong>You are not found:</strong>
<form>
<label>First name:<br>
<input type="text" name="firstname" value="Mickey">
</label>
<br>
<label>Last name:<br>
<input type="text" name="lastname" value="Mouse">
</label>
</form>
</div>
<button #click="method">Toggle</button>
</div>
It might be late but I am sure it will help others. Create a component ToggleButton.js and paste the below codes.
<template>
<label for="toggle_button">
<span v-if="isActive" class="toggle__label">On</span>
<span v-if="! isActive" class="toggle__label">Off</span>
<input type="checkbox" id="toggle_button" v-model="checkedValue">
<span class="toggle__switch"></span>
</label>
</template>
<script>
export default {
data() {
return {
currentState: false
}
},
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.defaultState
},
set(newValue) {
this.currentState = newValue;
}
}
}
}
</script>
Take a look at the article to learn more https://webomnizz.com/create-toggle-switch-button-with-vue-js/