Nuxt Module cannot find itself - javascript

./AppGallery.vue?vue&type=style&index=0&id=0cb54319&lang=scss&scoped=true& in ./components/sub-page/AppGallery.vue
AppGalery.vue doesn't import anything
<template>
<div class="gallery" v-if="pictures">
<a v-for="(picture, index) in pictures" :key="index" class="gallery__item" :href="picture.path" data-lightbox="gallery" :data-title="picture.title">
<div class="gallery__image">
<img :src="picture.path">
</div>
<div class="gallery__description" v-if="options.showDescription">{{ picture.title }}</div>
</a>
</div>
</template>
<script>
export default {
name: 'AppGallery',
props: {
pictures: {
type: Array,
required: true,
},
options: {
type: Object,
required: false,
default() {
return {
showDescription: true,
};
},
},
},
mounted() {
//lightbox.build();
},
};
</script>
On save error changes to other file.

Related

Can't correctly pass the props to the child component in Vue 3

I want to pass data from the request via axios in the root component to the child using Vue. Unfortunately, only one field is displayed correctly - "title". But I also need to output "body".
Ps: This is my first time working with Vue, and I would like to know how it can be done correctly
App.vue
<template>
<app-news
v-for="item in news"
:key="item.id"
:title="item.title"
:id="item.id"
:body="item.body"
>
</app-news>
</template>
export default {
data () {
return {
news: []
}
mounted() {
axios
.get('https://jsonplaceholder.typicode.com/posts?_start=0&_limit=5')
.then((resp) =>
this.news = resp.data
)
},
provide () {
return {
title: 'List of all news:',
news: this.news
}
},
AppNews.vue
<template>
<div>
<hr/>
<p v-for="item in news" :key="item.id">{{ item.body }}</p> // Need to pass here body content of the response from json
</div>
</template>
props: {
news: [], // -> I think here the problem, I need to get the response as a prop and validate them as well, as shown below
title: {
type: String,
required: true
},
id: {
type: Number,
required: true
},
body: {
type: String,
required: true
},
}
},
So :title="item.title",:id="item.id" and :body="item.body" will be passed as props. So you don't need extra props you can directly use that variable.
<template>
<div>
{{title}} <br/> {{body}} <br/> {{id}}
</div>
</template>
props: {
title: {
type: String,
required: true
},
id: {
type: Number,
required: true
},
body: {
type: String,
required: true
},
}
},
You can try like following snippet:
const app = Vue.createApp({
data() {
return {
news: []
}
},
async mounted() {
const news = await axios
.get('https://jsonplaceholder.typicode.com/posts?_start=0&_limit=5')
this.news = news.data
},
})
app.component('appNews', {
template: `
<div>
<hr/>
<p><b>{{ title }}<b></p>
<p>{{ body }}</p>
</div>
`,
props: {
title: {
type: String,
required: true
},
id: {
type: Number,
required: true
},
body: {
type: String,
required: true
},
}
})
app.mount('#demo')
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.1.3/axios.min.js" integrity="sha512-0qU9M9jfqPw6FKkPafM3gy2CBAvUWnYVOfNPDYKVuRTel1PrciTj+a9P3loJB+j0QmN2Y0JYQmkBBS8W+mbezg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<app-news
v-for="item in news"
:key="item.id"
:title="item.title"
:id="item.id"
:body="item.body"
>
</app-news>
</div>

Change content on left side when right side scrolled

I would like to create something similiar like tesla.com, content on left side will change when right side is scrolled.
I have tried create it using vuetify intersection, but it still buggy. Is there some way to improve it?
Here is demo for code i already created : https://hyundai-andalan.vercel.app/models/staria
This is code i using:
// page component
<template>
<div>
<ModelDesktop v-if="$vuetify.breakpoint.lgAndUp" />
<ModelMobile v-else />
</div>
</template>
<script>
import model from '~/mixins/model'
export default {
mixins: [model],
head () {
return {
title: this.model.name
}
}
}
</script>
// model desktop component
<template>
<div class="tw-grid tw-grid-cols-3">
<div class="tw-col-span-2">
<ModelCarousel :section="section" class="tw-sticky tw-top-0" />
</div>
<ModelDesktopContentWrapper #change:section="onSectionChange" />
</div>
</template>
<script>
export default {
data () {
return {
section: 'exterior'
}
},
methods: {
onSectionChange (value) {
this.section = value
}
}
}
</script>
// model carousel component
<template>
<v-carousel v-model="carousel" height="100vh">
<v-carousel-item
v-for="(item, i) in model[section].collection"
:key="i"
>
<v-img :src="item.image" aspect-ratio="1" eager />
</v-carousel-item>
</v-carousel>
</template>
<script>
import model from '~/mixins/model'
export default {
mixins: [model],
props: {
section: {
type: String,
default: 'exterior'
}
},
data: () => ({
carousel: 0,
colors: [
'primary',
'secondary',
'yellow darken-2',
'red',
'orange'
]
})
}
</script>
// model desktop component wrapper
<template>
<div class="tw-p-16">
<!-- Specification & Content -->
<div v-intersect="onExterior">
<ModelSpecification />
<ModelContent section="exterior" v-bind="model.exterior" />
</div>
<!-- Specification & Content -->
<!-- Interior -->
<ModelContent v-intersect="onInterior" section="interior" v-bind="model.interior" />
<!-- Interior -->
<!-- Interior -->
<ModelContent v-intersect="onPerformance" section="performance" v-bind="model.performance" />
<!-- Interior -->
<!-- Interior -->
<ModelContent v-intersect="onSafety" section="safety" v-bind="model.safety" />
<!-- Interior -->
</div>
</template>
<script>
import model from '~/mixins/model'
export default {
mixins: [model],
data () {
return {
exterior: false,
interior: false,
performance: false,
safety: false
}
},
watch: {
exterior (newValue) {
if (newValue) {
this.interior = false
this.performance = false
this.safety = false
this.$emit('change:section', 'exterior')
}
},
interior (newValue) {
if (newValue) {
this.exterior = false
this.performance = false
this.safety = false
this.$emit('change:section', 'interior')
}
},
performance (newValue) {
if (newValue) {
this.exterior = false
this.interior = false
this.safety = false
this.$emit('change:section', 'performance')
}
},
safety (newValue) {
if (newValue) {
this.exterior = false
this.interior = false
this.performance = false
this.$emit('change:section', 'safety')
}
}
},
methods: {
onExterior (entries) {
this.exterior = entries[0].isIntersecting
},
onInterior (entries) {
this.interior = entries[0].isIntersecting
},
onPerformance (entries) {
this.performance = entries[0].isIntersecting
},
onSafety (entries) {
this.safety = entries[0].isIntersecting
}
}
}
</script>
// model content component
<template>
<div>
<!-- Main Content -->
<div class="lg:tw-h-screen lg:tw-flex lg:tw-items-center tw-w-full">
<div class="lg:tw-flex-1">
<div class="tw-text-center">
<v-img v-if="$vuetify.breakpoint.mdAndDown" :src="banner" class="tw-mb-2" />
<h2 class="tw-capitalize">
{{ section }}
</h2>
<h3 class="tw-font-medium">
{{ title }}
</h3>
<div class="tw-mb-5" v-text="description" />
<v-btn rounded #click="dialogOpen = true">
feature detail
</v-btn>
</div>
</div>
</div>
<!-- Main Content -->
<ModelContentDialog v-model="dialogOpen" :section="section" :collection="collection" />
</div>
</template>
<script>
export default {
props: {
section: {
type: String,
required: true
},
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
banner: {
type: String,
default: ''
},
collection: {
type: Array,
required: true
}
},
data () {
return {
dialogOpen: false
}
}
}
</script>

Vue 3, where to listen for emit event

I'm sending an event from a child component to my parent component using $emit.
I know I should tell the parent component to listen to that event, however I don't know where to put the
#openModal="changeModalVisibility"
Should I do it as an attribute in the main div? Since this is the highest component I don't find the right place.
Child:
<template>
<div class="cocktail-result" v-on:click="openModal">
<img :src="cocktailImg" alt="cocktail-image" />
<p>{{ cocktailName }}</p>
<div class="explore-button">
<img
src="../assets/img/arrow-forward-icon.svg"
alt="arrow icon"
class="arrow-icon"
/>
</div>
</div>
</template>
<script>
export default {
name: "CocktailResult",
props: {
cocktailName: {
type: String,
},
cocktailImg: {
type: String,
},
modalClass: {
type: String,
},
},
methods: {
openModal() {
this.$emit("openModal");
},
},
};
</script>
Parent:
<template>
<div class="main-container" v-on:openModal="changeModalVisibility">
<div class="search-bar-container">
<img src="./assets/img/logo.png" alt="logo" class="logo" />
<div class="search-bar">
<input
type="text"
v-model="searchQuery"
class="search-bar-input"
placeholder="Enter Your Favorite Cocktail:"
#input="callCocktailApi"
/>
<img
src="./assets/img/close-icon.svg"
alt="close icon"
class="close-icon"
v-on:click="clearInput"
/>
</div>
</div>
<div class="result-container">
<ul v-for="(cocktail, index) in cocktailArray" :key="cocktail.key">
<CocktailResult
:cocktailName="this.cocktailArray[index].strDrink"
:cocktailImg="this.cocktailArray[index].strDrinkThumb"
:cocktailGlass="this.cocktailArray[index].strGlass"
:cocktailInstructions="this.cocktailArray[index].strInstructions"
:modalClass="this.modalClass"
:method="changeModalVisibility"
/>
</ul>
</div>
<CocktailModal :modalClass="this.modalClass" />
</div>
</template>
<script>
import CocktailResult from "./components/CocktailResult.vue";
import CocktailModal from "./components/CocktailModal.vue";
import axios from "axios";
export default {
name: "App",
data() {
return {
cocktailArray: "",
searchQuery: "",
cocktailName: "",
cocktailImg: "",
modalClass: "hidden",
};
},
components: {
CocktailResult,
CocktailModal,
},
methods: {
callCocktailApi() {
axios
.get(
`https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${this.searchQuery}
` // API Call
)
.then((res) => {
this.cocktailArray = JSON.parse(
JSON.stringify(res.data.drinks || [])
);
this.cocktailName = this.cocktailArray[0].strDrink;
// Only render results if an array is fetched
console.log(this.cocktailArray);
})
.catch((error) => {
console.log(error);
});
},
clearInput() {
this.cocktailArray = "";
this.searchQuery = "";
},
changeModalVisibility() {
this.modalClass = "";
console.log("I'm working");
},
},
};
</script>
You should put #openModal in your parent component, there were you call CocktailResult.
<CocktailResult
#openModal=“YourCallback”
…
/>

Error: Cannot find module './MessageFeed.vue'

Here's The Screenshot Of The Error:-
These Are The Files That I am Working On:-
Here's The Conversation.vue:-
<template>
<div class="conversation">
<h1>{{contact ? contact.name : 'Select a Contact'}}</h1>
<MessageFeed :contact="contact" :message="messages"/>
<MessageComposer #send="sendMessage"/>
</div>
</template>
<script>
import MessageFeed from './MessageFeed.vue';
import MessageComposer from './MessageComposer.vue';
export default {
props: {
contact: {
type: Object,
default: null
},
messages: {
type: Array,
default: []
}
},
methods: {
sendMessage(text){
console.log(text);
}
}
}
</script>
Here's The MessageFeed.vue:-
<template>
<div class="feed">
<ul v-if="contact">
<li v-for="message in messages" :class="`message${message.to == contact.id ? ' sent' : 'recieved'}`" :key="message.id">
<div class="text">
{{message.text}}
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
contact: {
type: Object,
required: true
},
message: {
type: Array,
required: true
}
}
}
</script>
I don't know anything about javaScript or the vue i was just following a tutorial and i stump upon this error couldn't find any solution
I didn't even knew what codes to put up here
but i hope this must be enough
-ThankYou
Try to rewrite scripts at Conversation.vue like there
<script>
import MessageFeed from './MessageFeed.vue';
import MessageComposer from './MessageComposer.vue';
export default {
components: {
MessageFeed,MessageComposer
},
props: {
contact: {
type: Object,
default: null
},
messages: {
type: Array,
default: []
}
},
methods: {
sendMessage(text){
console.log(text);
}
}
}
</script>

Vue Events - Can't listen to $emit event from child component

I'm having a simple issue, that I just can't figure out why it isn't working.
I have a child component "app-buttons", where i have an input field, i want to listen to, so i can filter a list based on the input value.
If i put the input in the root component where i have the list, all works good. But i want to split it up, and $emit the search input value, to the parent en then use it.
// THIS IS THE COMPONENT WHERE I WAN'T TO LISTEN TO THE SEARCH INPUT
import Buttons from './app-buttons.js';
import Event from './vue-event.js';
export default Vue.component('post-item', {
template: `
<section class="posts flex" v-if="posts">
<app-buttons :posts="posts"></app-buttons>
<transition-group name="posts" tag="section" class="posts flex">
<article class="postitem" :class="{ 'danger': !post.published }" v-for="post in posts" :key="post.id">
<p v-if="post.published">Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{{ post.title }}</h4>
<button type="submit" #click="post.published = !post.published">Change status</button>
</article>
</transition-group>
</section>
`,
data() {
return {
};
},
components: {
Buttons,
},
props: {
posts: Array,
filterdList: [],
},
created() {
console.log('%c Post items', 'font-weight: bold;color:blue;', 'created');
},
computed: {
//filteredList() {
// return this.posts.filter(post => {
// return post.title.toLowerCase().includes(this.search.toLowerCase());
// });
//},
},
methods: {
update() {
console.log('test');
}
}
});
// THIS IS THE COMPONENT IM TRIGGERING THE $EVENT FROM
import Event from './vue-event.js';
export default Vue.component('app-buttons', {
template: `
<div class="postswrapper flex flex--center flex--column">
<section :class="className" class="flex flex--center">
<button type="button" #click="showUnpublished">Unpublish</button>
<button type="button" #click="shufflePosts">Shuffle</button>
</section>
<section :class="className">
<input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." />
</section>
</div>
`,
data() {
return {
className: 'buttons',
search: '',
}
},
props: {
posts: Array,
},
created() {
//console.log(this);
console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created');
},
methods: {
updateValue() {
//console.log(this.search);
this.$emit('searchquery', this.search);
},
showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},
shufflePosts() {
this.$emit('postshuffled', 'Fisher-Yates to the rescue');
for (var i = this.posts.length - 1; i >= 0; i--) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];
Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue JS</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.6/dist/vue.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="app">
<app-header :logo="logo" :name="name"></app-header>
<post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item>
</div>
<script type="module">
import AppHeader from './components/app-header.js';
import PostItem from './components/post-item.js';
const app = new Vue({
el: '#app',
data: {
name: 'Vue App',
logo: {
class: 'vue-logo',
src: 'https://vuejs.org/images/logo.png',
},
components: {
AppHeader,
PostItem,
},
posts: [
{id: 1, title: 'Test', published: true},
{id: 2, title: 'New post', published: true},
{id: 3, title: 'Added', published: true},
{id: 4, title: 'Another post', published: true},
{id: 5, title: 'In the future', published: false},
{id: 6, title: 'Last post', published: true},
],
},
created() {
console.log('Created');
},
mounted() {
console.log('Mounted');
},
methods: {
update() {
console.log('updated');
}
},
});
</script>
</body>
</html>
You say:
I have a child component "app-buttons", where i have an input field, i
want to listen to, so i can filter a list based on the input value.
You have:
<div id="app">
<app-header :logo="logo" :name="name"></app-header>
<post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item>
</div>
That says you expect post-item to emit a searchquery event. It does not.
Within post-item, you have:
<app-buttons :posts="posts"></app-buttons>
So you expect app-buttons to emit an event and post-item to implicitly bubble it up, but Vue events do not bubble. If you want that behavior, you will need to have post-item handle the event:
<app-buttons :posts="posts" v-on:searchquery="$emit('searchquery', $event)"></app-buttons>
Okay so I've changed the markup, and it works. But would this be the best way to do it? :)
And thanks to Roy J for helping out.
import Event from './vue-event.js';
import Buttons from './app-buttons.js';
export default Vue.component('post-item', {
template: `
<section class="posts flex" v-if="posts">
<app-buttons :posts="posts" v-on:searchquery="update($event)"></app-buttons>
<transition-group name="posts" tag="section" class="posts flex">
<article class="postitem" :class="{ 'danger': !post.published }" v-for="post in filteredItems" :key="post.id">
<p v-if="post.published">Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{{ post.title }}</h4>
<button type="submit" #click="post.published = !post.published">Change status</button>
</article>
</transition-group>
</section>
`,
data() {
return {
search: '',
};
},
components: {
Buttons,
},
props: {
posts: Array,
},
created() {
console.log('%c Post items', 'font-weight: bold;color:blue;', 'created');
},
computed: {
filteredItems(search) {
return this.posts.filter(post => {
return post.title.toLowerCase().indexOf(this.search.toLowerCase()) > -1
});
}
},
methods: {
update(event) {
this.search = event;
}
}
});
// Child component
import Event from './vue-event.js';
export default Vue.component('app-buttons', {
template: `
<div class="postswrapper flex flex--center flex--column">
<section :class="className" class="flex flex--center">
<button type="button" #click="showUnpublished">Unpublish</button>
<button type="button" #click="shufflePosts">Shuffle</button>
</section>
<section :class="className">
<input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." />
</section>
</div>
`,
data() {
return {
className: 'buttons',
search: '',
}
},
props: {
posts: Array,
},
created() {
console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created');
},
methods: {
updateValue() {
this.$emit('searchquery', this.search);
},
showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},
shufflePosts() {
for (var i = this.posts.length - 1; i >= 0; i--) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];
Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
Index same as before, just without alle the events on the components.

Categories

Resources