Newsletter - Subscribe (CMS website)
Below you can find an implementation example how to subscribe to a Deploytec(Clang) newsletter in your Nuxt 3 app. Usually this is a website connected the Snakeware CMS.
Example: Logeren Bij De Boswachter - Footer
- server: folder:
server/api/newsletter/subscribe.ts
- client: folder:
components/items/deployteqsubscribtion.ts
Client
<template>
<div class="newsletter">
<span>{{ content.title.value }}</span>
<form-input
v-model="email"
class="input"
label="Email"
autocomplete="email"
:placeholder="placeholder"
:error="error"
:data-attrs="dataAttrs"
@keydown.enter="submit"
@submit="submit"
@blur="clear"
@focus="clear"
/>
</div>
</template>
<script lang="ts" setup>
import { IItem } from '@snakeware/snakeware.api.site.typescript'
import { PropType } from 'vue'
const { t: translate } = useI18n()
const loading = ref(false)
const email = ref<string>()
const error = ref<string>()
const props = defineProps({
item: {
type: Object as PropType<IItem>,
default: null
}
})
const dataAttrs = {
location: 'footer',
itemType: props.item.alias,
item: 'form-x-sent',
style: 'form'
}
const content = useSwGetControls(props.item)
const placeholder = computed(
() => `${translate('testing.newsletter.placeholder')}`
)
const clear = () => (error.value = '')
const submit = async () => {
if (
(email.value && email.value.length < 4 && !email.value.includes('@')) ||
(email.value && !email.value.includes('.'))
) {
error.value = translate('testing.newsletter.error')
return
}
loading.value = true
if (typeof window !== 'undefined') {
const res = await $fetch<{ url: string }>('/api/newsletter/subscribe', {
method: 'POST',
body: {
email: email.value?.toString()
}
})
if (res.url) {
await navigateTo(
{
path: res.url,
query: {
'newsletter-success': 'true'
}
},
{ external: true }
)
} else {
error.value = translate('testing.error.general')
loading.value = false
}
}
}
</script>
<style lang="scss" scoped>
.newsletter {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
width: 100%;
gap: 1.6rem;
@include breakpoint(st) {
flex-direction: row;
justify-content: flex-end;
align-items: center;
gap: 0;
}
span {
display: inline-block;
margin-right: 1.6rem;
}
.input {
width: 100%;
border-bottom: 1px solid var(--grey-2-color);
@include breakpoint(st) {
width: 24rem;
}
}
}
</style>