I know there are several other questions about it, but none of them seems to help me.
I'm trying to create a simple Image component, but I images are not loading since I tried to use them in a component.
<template>
<!-- <img :click="go()" :src="require(`../assets/img/${filename}`)"> -->
<img :click="go()" :src="`../assets/img/'${filename}`">
</template>
<script>
export default {
name: 'Imagem',
data() {
return {
filename: ''
}
},
methods: {
go() {
console.log('image click')
}
}
}
</script>
<style scoped>
img{
min-width: 20%;
}
</style>
The first line throws error:
The second line, without require, gives no error but don't load the image (i restarted the project and cleaned cache)
This is the view where Imagem component is imported:
<template>
<div class="login-images">
<!-- <img #click="novoProfessor" src="../assets/professor.png" alt="" srcset="">
<img #click="novoAluno" src="../assets/aluno.png" alt="" srcset=""> -->
<Imagem :filename="'professor.png'" />
<Imagem :filename="'aluno.png'" />
</div>
</template>
<script>
import Imagem from '../components/Imagem';
export default {
name: 'Login',
components: {
Imagem
},
props: {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.login-images {
min-width: 100%;
min-height: 50%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.login-images > * {
margin: 10%;
}
</style>
Change your Imagem component like this:
<template>
<img :src="imageURL" #click="go">
</template>
<script>
export default
{
name: 'Imagem',
props:
{
filename:
{
type: 'String',
required: true
}
},
computed:
{
imageURL()
{
return `../assets/img/${this.filename}`;
}
},
methods:
{
go(event)
{
console.log('You clicked on the "' + event.target.src + '"');
}
}
}
</script>
Related
I'm using Vue2 and Bootstrap-Vue. I have a table with data (I use b-table). I want to have "edit" option on each row in order to edit the table. This option (which is an icon of gear) will open a modal and display a view boxes. In my view I have:
<template>
<div>
<b-table class="text-center" striped hover
:items="items"
:bordered=tableBordered
:fields=tableFields
:label-sort-asc=tableLabelSortAsc>
<template #cell(view)="data">
<a target="_blank" rel="noopener" class="no-link" :href="data.item.url">
<b-icon icon="eye-fill"/>
</a>
</template>
<template #cell(edit)="data">
<b-icon icon="gear-fill"/>
<edit-info-modal :data="data"/>
</template>
</b-table>
</div>
</template>
<script>
import EditInfoModal from './EditInfoModal.vue';
import { BIcon } from 'bootstrap-vue';
export default {
components: {
'b-icon': BIcon,
'edit-info-modal': EditInfoModal
},
data() {
return {
tableBordered: true,
tableLabelSortAsc: "",
tableFields: [
{ sortable: false, key: 'edit', label: 'edit' },
{ sortable: true, key: 'comments', label: 'comments' },
{ sortable: false, key: 'view', label: 'view' }
],
items: [
{
"comments": "test",
"url": "some_url"
}
]
}
}
}
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
a.no-link {
color: black;
text-decoration: none;
}
a:hover.no-link {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
It creates a table with three columns - the view column (with eye icon) which redirects to the url, the comments column and the edit column (with gear icon) which should open the modal.
Now, I'm trying to have the modal in a separated Vue file called EditInfoModal:
<template>
<div>
<b-modal id="modal-1" title="BootstrapVue">
<p class="my-4">Hello from modal!</p>
</b-modal>
</div>
</template>
<script>
import { BModal } from 'bootstrap-vue';
export default {
props: {
data: Object
},
components: {
'b-modal': BModal
}
}
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
</style>
First of all, it does not open the modal. Reading over the internet I noticed that I should add isModalOpen field and update it each time and then create the watch method. But here I have a modal for each row. What is the recommended way to keep track of the opened modal (only one is opened at any given time)?
Step 1: install BootstrapVue package and references in main.js
import { BootstrapVue, BootstrapVueIcons } from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
Vue.use(BootstrapVueIcons);
Step 2: App.vue component
<template>
<div id="app">
<b-table
class="text-center"
striped
hover
:items="items"
:bordered="tableBordered"
:fields="tableFields"
:label-sort-asc="tableLabelSortAsc">
<template #cell(view)="data">
<a target="_blank" rel="noopener" class="no-link" :href="data.item.url">
<b-icon icon="eye-fill" />
</a>
</template>
<template #cell(edit)="data">
<b-icon icon="gear-fill" #click.prevent="editTable(data)" />
</template>
</b-table>
<edit-info-modal :data="data" :showModal="showModal" />
</div>
</template>
<script>
import { BIcon, BTable } from "bootstrap-vue";
import EditInfoModal from "./components/EditInfoModal.vue";
export default {
name: "App",
components: {
"b-table": BTable,
"b-icon": BIcon,
"edit-info-modal": EditInfoModal,
},
data() {
return {
tableBordered: true,
tableLabelSortAsc: "",
tableFields: [
{ sortable: false, key: "edit", label: "edit" },
{ sortable: true, key: "comments", label: "comments" },
{ sortable: false, key: "view", label: "view" },
],
items: [
{
comments: "Vue CRUD Bootstrap app",
url: "https://jebasuthan.github.io/vue_crud_bootstrap/",
},
{
comments: "Google",
url: "https://www.google.com/",
},
],
data: "",
showModal: false,
};
},
methods: {
editTable(data) {
this.data = Object.assign({}, data.item);;
this.showModal = true;
// this.$root.$emit("edit-table", Object.assign({}, data));
// this.$bvModal.show("modal-1");
},
},
};
</script>
<style scoped>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
div {
margin: auto 0;
width: 100%;
}
a.no-link {
color: black;
text-decoration: none;
}
a:hover.no-link {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
Step 3: Child component EditInfoModal.vue
<template>
<div>
<b-modal v-model="showModal" id="modal-1" title="Edit Table">
<p class="my-4">Hello from modal!</p>
<p>Comments: {{ data.comments }}</p>
<p>
URL: <a :href="data.url">{{ data.url }}</a>
</p>
</b-modal>
</div>
</template>
<script>
import { BModal } from "bootstrap-vue";
export default {
// data() {
// return {
// data: "",
// showModal: "",
// };
// },
props: ["data", "showModal"],
components: {
"b-modal": BModal,
},
// mounted() {
// this.$root.$on("edit-table", (data) => {
// this.data = data.item;
// });
// },
};
</script>
<style scoped>
div {
margin: auto 0;
width: 100%;
}
</style>
DEMO Link
i wanted to get the computed data and display in another component. However i put the computed in my app.vue and try to call this computed using :style="inputStyles" in my ChangeBackground.vue . But when i try to do this it showing error that " Property or method "inputStyles" is not defined on the instance but referenced during render" Can someone help me? Thank you
You can access the code here:
https://codesandbox.io/s/hardcore-morning-5ch1u?file=/src/components
Here is the code:
App.vue
<template>
<div id="app">
<ChangeBackground msg="Hello Vue in CodeSandbox!" />
</div>
</template>
<script>
import ChangeBackground from "./components/ChangeBackground";
export default {
name: "App",
components: {
ChangeBackground,
},
data() {
return {
bgColor: "red",
};
},
created() {
this.bgColor = "#F6780D";
},
computed: {
inputStyles() {
return {
background: this.bgColor,
};
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
body {
background-color: blue;
}
</style>
ChangeBackground.vue
<template>
<div class="hello" :style="inputStyles">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "Getting the computed area here to change the background",
};
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
h1,
h2 {
font-weight: bold;
}
ul {
list-style-type: none;
padding: 1rem;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
You should pass it as prop as you did with msg :
App.vue
<ChangeBackground msg="Hello Vue in CodeSandbox!" :input-styles="inputStyles" />
ChangeBackground.vue
<template>
<div class="hello" :style="inputStyles">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props:["inputStyles"],//⬅
data() {
return {
msg: "Getting the computed area here to change the background",
};
},
};
</script>
index.vue -
<template>
<div>
<Header />
<div class="container">
<SearchForm />
</div>
</div>
</template>
<script>
const Cookie = process.client ? require('js-cookie') : undefined
export default {
data() {
return {
form: {
email: '',
password: ''
},
show: true
}
},
methods: {
logout() {
// Code will also be required to invalidate the JWT Cookie on external API
Cookie.remove('auth')
this.$store.commit('setAuth', {
auth: null,
user_type: null
})
}
}
}
</script>
<style>
.container {
/* margin: 0 auto; */
/* min-height: 100vh; */
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>
jobs.vue -
<template>
<div>
<Header />
<SearchForm />
<b-container class="main_container">
<b-row>
<h1> Results for "{{q}}"</h1>
</b-row>
<b-row>
<ul id="array-rendering">
<li v-for="item in results" :key="item.job_id">
{{ item.job_title }}
{{ item.job_city }}
{{ item.job_state }}
{{ item.job_work_remote }}
</li>
</ul>
</b-row>
</b-container>
</div>
</template>
<script>
const Cookie = process.client ? require('js-cookie') : undefined
export default {
// middleware: 'notAuthenticated',
watchQuery: ['q'],
data() {
return {
q: null,
results: []
}
},
async fetch() {
this.q = this.$route.query.q
this.results = await this.$axios.$get('/api/job/search', {
params: {
keyword: this.q,
}
})
},
methods: {
}
}
</script>
<style>
.container {
align-items: center;
text-align: center;
}
</style>
SearchForm.vue component -
<template>
<div id='searchFormDiv'>
<b-form inline #submit.prevent="onSubmit">
<label class="sr-only" for="inline-form-input-name"> keyword</label>
<b-form-input v-model="form.keyword" id="inline-form-input-name" class="mb-2 mr-sm-2 mb-sm-0" placeholder="Job title or keyword" size="lg"></b-form-input>
<label class="sr-only" for="inline-form-input-username">location</label>
<b-input-group class="mb-2 mr-sm-2 mb-sm-0">
<b-form-input v-model="form.location" id="inline-form-input-username" size="lg" placeholder="City, state or zip"></b-form-input>
</b-input-group>
<b-button type="submit" variant="primary">Find Jobs</b-button>
</b-form>
</div>
</template>
<script>
import {
BIconSearch,
BIconGeoAlt
} from 'bootstrap-vue'
export default {
data() {
return {
form: {
keyword: '',
location: ''
}
}
},
created () {
this.form.keyword = this.$route.query.q
},
methods: {
onSubmit() {
this.$router.push({
path: 'jobs',
query: {
q: this.form.keyword
}
});
}
},
components: {
BIconSearch,
BIconGeoAlt
},
}
</script>
<style>
#searchFormDiv {
margin-top: 50px
}
</style>
The route for "http://localhost:3000/" returns the index.vue page.
In this vue page, I have a component with a search form. Once you complete these form and hit the seach button, it will re-direct to a results page
if this.form.keyword = "Data", the next URL will be "http://localhost:3000/jobs?q=Data" and it will be using the jobs.vue page.
The issue I'm running into is the CSS is not being loaded from the jobs.vue page. It's still coming from the index.vue page for some reason. If I refresh the page, then the CSS from jobs.vue is loading. I need the CSS to load from jobs.vue on the initial redirect. All of the query data is working as expected so thats a plus.
However, the following CSS is being applied from index.vue for some reason instead of the CSS from the jobs.vue page -
display: flex;
justify-content: center;
Does anyone know whats going on here? This app is SSR and not SPA.
You have to scope your css from the index.vue page to the other pages with the scoped directive (see docs https://vue-loader.vuejs.org/guide/scoped-css.html)
<style scoped>
/* local styles */
</style>
<style>
/* global styles */
</style>
You can add your global CSS in your layouts/default.vue file.
This solved the issue -
methods: {
onSubmit() {
window.location = 'http://localhost:3000/jobs?q=' + this.form.keyword;
}
},
I have a variable in my parent component and would like it to be sent to the child component.
I tried several ways but nothing works on my side, here is my code:
Parent :
<template>
<Widget/>
</template>
<script>
import Widget from './Widget'
export default {
data () {
return {
model: {
data: 'data send !'
}
}
},
components: {
Widget
},
methods: {
}
}
</script>
Child :
<template>
<div class="row">
<div class="box">
<p> {{data}} </p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
data: '111'
}
}
}
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>
thank you in advance for your help!
To bind data to a child component you can use props.
Parent :
<template>
<Widget :data="model.data"/>
</template>
<script>
import Widget from "./Widget";
export default {
data() {
return {
model: {
data: "data send !"
}
};
},
components: {
Widget
},
methods: {}
};
</script>
Child:
<template>
<div class="row">
<div class="box">
<p>{{data}}</p>
</div>
</div>
</template>
<script>
export default {
props: ["data"]
};
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>
After googling for hours and trying all king examples I still can't figure out how to call to a function that located in a child or pass any data to a child from the parent. I tried so many examples without success and i got really confused with the Vue, is it so complicated to pass a data to a child? Here is what I came up with from one of the examples but it does not work with me, maybe I do something wrong here? Thanks :(
parent.vue
<template>
export default {
name:'parent'
data:{
retrun:{
dataTochild:''
}
},
methods:{
callToChild:function(){
this.dataTochild = 'Hello Child'
}
}
}
</template>
<child :myprop="dataTochild" />
<input #click="this.callToChild" />
child.vue
<template>
export default {
name:'child',
props:['myprop'],
watch:{
myprop:function(){
alert('Hello Parent')
}
}
}
<template>
By the way, I am using Vue 2 version!
you have a spelling error on return (retrun), and there could be other errors on code you have omitted.
Working live demo
Here it is working on a live demo
Code
Parent
<template>
<div class="parent">
<child :myprop="dataTochild" />
<button #click="callToChild">Press me!</button>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Parent",
data() {
return {
dataTochild: "",
counter: 0
};
},
methods: {
callToChild: function() {
this.counter = this.counter + 1;
this.dataTochild = "Hello Child " + this.counter;
}
},
components: {
Child
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
button {
width: 200px;
height: 60px;
}
</style>
Child
<template>
<div class="child">
<p>{{ myprop }}</p>
</div>
</template>
<script>
export default {
name: "Child",
props: ["myprop"],
watch: {
myprop: function() {
console.log("Hello Parent");
alert("Hello Parent");
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
div.child {
width: 400px;
height: 100px;
margin: auto;
}
</style>