JAMStack: how to impelement E-Mail Services or simple reactive variables? - vue.js

I'm currently working on a marketing website for a client. Because SSR would be over-engineered and I'm curious about JAMStack, I decided to make a static website using Nuxt, because I'm already familiar with it.
So I managed to implement Tailwind, which works fine, also when the static site is generated and live on Github pages for example. Now I want to add a feature like a send e-mail form or a menu with a toggle icon.
The simplest solution I could think of for the menu would be a reactive variable and conditional rendering using tailwind. This works fine on localhost using npm run dev, but I can't figure out how to implement this on the generated static site.
I couldn't even manage to fire a click event to a defined method in the script tag.
That's how I would do the burger menu with nuxt SRR, how can I implement something like this in static generated nuxt?
<template>
<div>
<nav
class="flex p-5 items-center fixed w-full border-b-4 border-green bg-white z-50 duration-300 transform justify-between">
<div>
<div><img src="logo.png" class="max-h-6 md:max-h-10" /></div>
</div>
<div class="w-10 h-5 flex flex-col relative cursor-pointer" id="nav-menu" #click="menuOpen = !menuOpen">
<div class="w-full h-1 bg-green absolute duration-200 transform "
:class="[menuOpen ? 'rotate-45 translate-y-2' : 'burger-hover1']" id="menu-first"></div>
<div class="w-full h-1 bg-green absolute bottom-0 duration-200 transform "
:class="[menuOpen ? '-rotate-45 -translate-y-2' : 'burger-hover2']" id="menu-second"></div>
</div>
</nav>
<Transition>
<div v-if="menuOpen" class="fixed w-screen h-screen bg-white pt-20 z-30 space-y-10 text-xl text-center">
<div class="mt-20" #click="menuOpen = !menuOpen">
<nuxt-link to="/">Start</nuxt-link>
</div>
<div #click="menuOpen = !menuOpen">
<nuxt-link to="/partner">Partner</nuxt-link>
</div>
<div #click="menuOpen = !menuOpen">
<nuxt-link to="/kontakt">Kontakt</nuxt-link>
</div>
<div #click="menuOpen = !menuOpen">
<nuxt-link to="/impressum">Impressum</nuxt-link>
</div>
</div>
</Transition>
</div>
</template>
<script>
export default {
name: 'Navbar',
data() {
return {
menuOpen: false
}
}
}
</script>
That's how it looks on localhost. When the static site is hosted, it won't toggle the menu.

Related

How to get ID from conditionally rendered item in modal component?

I have a conditionally-rendered notes and I want to delete specific note, depends on ID.
I have no problem with deleting without modal, but my problem is that I want to delete note only when modal is accepted.
There is modal component:
<DeleteModal
:modalVisible="modalVisible"
:restore="modalType"
#closeModal="modalVisible = false"
#deleteItem="deleteNote(note.id)"
#restoreItem="restore()"
/>
Delete method:
const deleteNote = (id) => {
Inertia.delete(route('notes.destroy', id));
getNotes();
};
and there is how I render notes:
<div class="my-4" v-for="note in notesForIssue" :key="note">
<div class="flex flex-row justify-between"></div>
<div class="bg-gray-100 w-full min-h-16 mt-2 rounded whitespace-normal">
<div class="px-8 py-4">
<p>{{ note.text }}</p>
<div class="flex flex-row items-center justify-between">
<div class="flex flex-row text-xs">
<span class="text-[#2563EB]">{{ note.updated_at }}</span>
<p class="ml-2">{{ __('history.by') }}</p>
<p class="font-bold ml-2 text-[#2563EB]">{{ note.updated_by }}</p>
</div>
<div #click="modalType=false; modalVisible=true;">
</div>
</div>
</div>
</div>
</div>
But I have no access to note.id here: #deleteItem="deleteNote(note.id)". Any ideas, how to solve this problem?
Try this approach.
When you click on the div, instead of set visibality of modal,
set selectedItem
set visibility
then you accept by modal, you have a `selectedItem' for delete
After delete, clear the selectedItem.
First the key attribute is not accpet object type variable. Second maybe you should check what is notesForIssue first ,then find out why you can't access note.id

Global CSS doesn’t work when programmatically change route

My index page has a Header and Home components.
{
path: "/",
name: "Homepage",
components: {
header: () => import("../components/layout/HomepageHeader.vue"),
main: () => import("../views/Home.vue"),
},
},
Both don’t have any scoped CSS, they only use Tailwind CSS classes. And that Tailwind CSS file is global.
The problem occurs when I programmatically redirect to my index page (for example, after I logged in). The HomepageHeader component doesn’t have all the CSS. Same with the Home.vue component.
Here’s the simplified code of the Header
<template>
<div class="w-full bg-white sm:shadow-lg mb-6">
<div class="mx-6">
<nav
class="px-3 flex flex-col sm:flex-row sm:px-4 sm:justify-between sm:h-16 list-none"
>
<li
class="text-center h-16 font-semibold text-red-500 text-lg sm:text-xl sm:h-16 table"
>
<div class=" py-4 sm:h-16">
<router-link to="/">Home</router-link>
</div>
</li>
<li>
<login-badge
class="shadow-lg md:shadow-none px-4 py-3 flex sm:px-0 sm:h-14 text-white"
></login-badge>
</li>
</nav>
</div>
</div>
</template>
When I say
“component doesn’t have all the CSS”
I mean that all the classes in the HomepageHeader.vue component don’t work. But the classes inside the child component LoginBadge.vue work fine!
What else can I say? I use router.replace("/"); to redirect to the homepage.
How do I fix that?
P.S. Just found out that the same thing happends when I go back to a previous page and that previous page is the index page.
P.P.S. global CSS is imported inside the App.vue
<template>
<router-view name="header"></router-view>
<main class="container mx-auto">
<router-view name="main"></router-view>
</main>
</template>
<script>
export default {
setup() {
return {};
},
};
</script>
<style>
#import "./assets/tailwind.css";

Nuxt.js/Vue.js dynamic images is not working

I'm getting some data from an API that contains an image and some other information. Now there's a problem in Nuxt js or maybe I'm wrong. Whenever I supply the path to the image in the :src it just doesn't work.
Here's my code:
<div v-for="(project, index) in projects" :key="project.p_id" class="swiper-slide">
<div :id="`index_${index}`" class="slide_wrapper">
<div class="background">
<img :src="getImgUrl(project.p_img_path)" alt="project cover image" />
</div>
<div class="details">
<div>
<div class="left">
<h2 style="color: black !impor tant">{{ project.p_label }}</h2>
<small>{{ project.p_date }}</small>
</div>
<div class="right">
<nuxt-link class="btn btn-secondary" to="/" #click="readMore">
<i class="fas fa-ellipsis-h"></i>
</nuxt-link>
</div>
</div>
</div>
</div>
</div>
script:
props: ['projects'],
methods: {
readMore() {},
getImgUrl(path) {
return '../../../' + path
},
},
Last thing, whenever I use required required('./assets/'+image.jpg') nuxt.js crushes in compilation always stops at 69%. I also tried required.context but it didn't work as well.
Any help will be appreciated. Thanks in advance.
In your template, change:
<img :src="getImgUrl(project.p_img_path)" alt="project cover image">
To:
<img :src="require(`../assets/${project.p_img_path}`)" alt="project cover image">
You shouldn’t need a method to return the path as a string, just use a template literal as above.
Ps. This assumes project.p_img_path = img/project_img/filename.jpg, so adjust as necessary.
The solution is that I had to put all the images inside the assets folder directly. Thank you all for your time.

Vuejs and Slick Carousel - problem with v-for can't add element in carousel

I'm using vue-slick component but I have some problem with the v-for loop.
This is my code:
<slick
ref="slick"
:options="slickOptions"
class="float-left full-width slider-ingredients">
<div
v-for="ingredient in available_prots_source"
:key="ingredient.id"
#click="onSelectIngredient(ingredient.id, 'prots')"
class="slider-ingredient-item">
<div class="float-left ingredient-image">
<div class="content">
<img :src="ingredient.image" width="200" height="200" class="float-left cover-fit">
</div>
</div>
<h4 class="float-left full-width text-center ingredient-name">
{{ingredient.name}}
</h4>
<span class="float-left full-width text-center ingredient-details">
dettagli
</span>
</div>
</slick>
The problem is that my div is added outside the slick container. If I add a <div> just after the <slick> opening tag it render correctly but sees just one element even if my v-for add 4 or 5 elements.
What am I doing wrong?
How can I use slick with v-for loops?
from the official README (see method reInit in the README.md
// Helpful if you have to deal with v-for to update dynamic lists
this.$nextTick(() => {
this.$refs.slick.reSlick();
});

How can I load different components in the same page

Each user type in my app needs to have a different dashboard, so, at the moment, my admin vue looks like the following:
<template>
<main id="admin-main">
<header id="admin-dashboard-header" class="jumbotron">
<div>
<h1>Job Dashboard</h1>
<p>Worker > Dashboard</p>
</div>
</header>
<div class="row container">
<div class="col-4">
<ul class="list-group text-center">
<li class="list-group-item active">Dashboard</li>
<li class="list-group-item">Companies</li>
<li class="list-group-item">Jobs</li>
<li class="list-group-item">Candidates</li>
</ul>
</div>
<div class="col-8">
All components must load here
</div>
</div>
</main>
</template>
<style scoped>
h1{
font-size: 50px;
}
</style>
Ideally, each list item(Companies, Jobs, Candidates) must load their respective component.
So, for instance, how can I load jobs component in this same page when I click on the jobs list item?
One solution would be to use dynamic components. See: https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components
You can see an example I made here: https://codepen.io/bergur/pen/bPEJdB
In my Vue app I've made a data property called selectedComponent, and defined a method that sets that property according to the parameter
setComponent(name) {
this.selectedComponent = name
}
You then invoke that function with something like:
<button #click="setComponent('menuList')">Menu List</button>
And here is the real magic
<component :is="selectedComponent" />
So when I press the button. The data property selectedComponent gets the value menuList which is the registered component.
The component tag then renders that component.