Skip to main content

Nuxt 3 Integration

Learn how to set up Vue Print It in your Nuxt 3 application using client-side plugins.

Installation

Install the package in your Nuxt 3 project:
npm install vue-print-it

Setup

1
Create a Client Plugin
2
Create a plugin file at plugins/vue-print-it.client.ts:
3
The .client.ts suffix is crucial - it ensures the plugin only runs on the client side, which is necessary for printing functionality.
4
import { createVuePrintIt } from 'vue-print-it'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(createVuePrintIt({
    // Global configuration for your Nuxt app
    windowTitle: 'Nuxt Print Document',
    preserveStyles: true,
    autoClose: true,
    timeout: 1500,
    specs: { width: 1024, height: 768 },
    globalMethodName: '$nuxtPrint' // Optional: Nuxt-specific method name
  }))
})
5
Use in Pages and Components
6
The plugin automatically registers the print functionality globally.

Usage

Using Global Method

Access the print function through the Nuxt app context:
<template>
  <div>
    <div id="nuxt-content">
      <h1>{{ $route.meta.title || 'Nuxt Page' }}</h1>
      <p>This is a Nuxt page with printable content.</p>
      <NuxtImg src="/logo.png" alt="Logo" />
    </div>
    
    <button 
      class="btn btn-primary" 
      @click="handlePrint"
    >
      Print Page
    </button>
  </div>
</template>

<script setup lang="ts">
const { $print } = useNuxtApp()

function handlePrint() {
  // Using global method
  $print('nuxt-content', {
    windowTitle: `Print - ${useRoute().meta.title}`,
    styles: [
      '@media print { .no-print { display: none; } }'
    ]
  })
}
</script>

Using the Composable

For more flexibility, use the usePrint composable:
<template>
  <div>
    <div id="article-content">
      <h1>{{ article.title }}</h1>
      <p>{{ article.content }}</p>
    </div>
    
    <button @click="printArticle">Print Article</button>
  </div>
</template>

<script setup lang="ts">
import { usePrint } from 'vue-print-it'

const { print } = usePrint()
const route = useRoute()

const article = ref({
  title: 'My Article',
  content: 'Article content here...'
})

function printArticle() {
  print('article-content', {
    windowTitle: article.value.title,
    onBeforePrint: () => {
      console.log('Printing from Nuxt app...')
    },
    onAfterPrint: () => {
      console.log('Print completed!')
    }
  })
}
</script>

With Custom Method Name

If you configured a custom method name:
<script setup lang="ts">
const { $nuxtPrint } = useNuxtApp()

function printPage() {
  $nuxtPrint('content-id', {
    windowTitle: 'Custom Document'
  })
}
</script>

Advanced Examples

Dynamic Route-Based Printing

Print content with route-specific configuration:
<template>
  <div>
    <div id="page-content">
      <h1>{{ page.title }}</h1>
      <div v-html="page.content"></div>
    </div>
    
    <button @click="printCurrentPage">Print This Page</button>
  </div>
</template>

<script setup lang="ts">
import { usePrint } from 'vue-print-it'

const { print } = usePrint()
const route = useRoute()

const page = await useAsyncData('page', () => 
  $fetch(`/api/pages/${route.params.id}`)
)

function printCurrentPage() {
  print('page-content', {
    windowTitle: `${page.value.title} - Print`,
    styles: [
      '@page { margin: 1in; }',
      'body { font-family: Georgia, serif; }'
    ]
  })
}
</script>
Show feedback during the print process:
<template>
  <div>
    <div id="report">
      <h1>Sales Report</h1>
      <table>
        <!-- Report content -->
      </table>
    </div>
    
    <button 
      @click="printReport" 
      :disabled="isPrinting"
    >
      {{ isPrinting ? 'Printing...' : 'Print Report' }}
    </button>
    
    <p v-if="printStatus">{{ printStatus }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { usePrint } from 'vue-print-it'

const { print } = usePrint()
const isPrinting = ref(false)
const printStatus = ref('')

function printReport() {
  print('report', {
    windowTitle: 'Sales Report',
    onBeforePrint: () => {
      isPrinting.value = true
      printStatus.value = 'Preparing document...'
    },
    onAfterPrint: () => {
      isPrinting.value = false
      printStatus.value = 'Print completed successfully!'
      setTimeout(() => printStatus.value = '', 3000)
    },
    onPrintError: (error: Error) => {
      isPrinting.value = false
      printStatus.value = `Print failed: ${error.message}`
    }
  })
}
</script>

Server-Side Rendered Content

Print SSR content with proper styling:
<template>
  <div>
    <article id="ssr-content">
      <h1>{{ post.title }}</h1>
      <div class="meta">
        <span>By {{ post.author }}</span>
        <time>{{ formatDate(post.date) }}</time>
      </div>
      <div class="content" v-html="post.body"></div>
    </article>
    
    <button class="no-print" @click="printPost">Print Article</button>
  </div>
</template>

<script setup lang="ts">
import { usePrint } from 'vue-print-it'

const { print } = usePrint()

// Fetch data on server
const { data: post } = await useAsyncData('post', () => 
  $fetch('/api/posts/1')
)

const formatDate = (date: string) => {
  return new Date(date).toLocaleDateString()
}

function printPost() {
  print('ssr-content', {
    windowTitle: post.value.title,
    preserveStyles: true,
    styles: [
      '@media print {',
      '  .no-print { display: none; }',
      '  article { max-width: 100%; }',
      '  .meta { font-size: 12px; color: #666; }',
      '}'
    ]
  })
}
</script>

Configuration Options

Plugin Configuration

Configure global defaults in your plugin file:
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(createVuePrintIt({
    windowTitle: 'Nuxt Print Document',
    preserveStyles: true,
    autoClose: true,
    timeout: 1500,
    specs: { width: 1024, height: 768 },
    globalMethodName: '$nuxtPrint',
    styles: [
      // Global print styles
      '@page { size: A4; margin: 1cm; }',
      '@media print { .no-print { display: none !important; } }'
    ]
  }))
})

Runtime Configuration

Override defaults for specific print operations:
print('element-id', {
  windowTitle: 'Custom Title',
  specs: { width: 800, height: 600 },
  timeout: 2000,
  autoClose: false,
  styles: ['body { font-size: 14px; }'],
  onBeforePrint: async () => {
    // Async operations before printing
    await fetchAdditionalData()
  }
})

Best Practices

Client-Only Components

Wrap print functionality in <ClientOnly> if needed:
<template>
  <div>
    <div id="content">Content here</div>
    
    <ClientOnly>
      <button @click="$print('content')">Print</button>
    </ClientOnly>
  </div>
</template>

Composable Pattern

Create a custom composable for reusable print logic:
// composables/usePrintPage.ts
import { usePrint } from 'vue-print-it'

export const usePrintPage = () => {
  const { print } = usePrint()
  const route = useRoute()
  
  const printPage = (elementId: string) => {
    print(elementId, {
      windowTitle: `${route.meta.title || 'Page'} - Print`,
      preserveStyles: true,
      styles: [
        '@media print { .no-print { display: none; } }'
      ]
    })
  }
  
  return { printPage }
}
Use it in components:
<script setup lang="ts">
const { printPage } = usePrintPage()
</script>

<template>
  <button @click="printPage('content')">Print</button>
</template>

TypeScript Support

Add type definitions for the global method:
// types/vue-print-it.d.ts
import type { PrintOptions } from 'vue-print-it'

declare module '#app' {
  interface NuxtApp {
    $print: (element: HTMLElement | string, options?: PrintOptions) => Promise<void>
    $nuxtPrint: (element: HTMLElement | string, options?: PrintOptions) => Promise<void>
  }
}

export {}

Troubleshooting

Plugin Not Loading

Ensure your plugin file has the .client.ts suffix:
plugins/vue-print-it.client.ts  ✓ Correct
plugins/vue-print-it.ts         ✗ Wrong (will try to run on server)

SSR Errors

If you encounter SSR errors, wrap print functionality in client checks:
if (process.client) {
  $print('element-id')
}

Styles Not Preserved

Make sure preserveStyles: true is set in your plugin configuration.

Next Steps

Configuration

Explore all configuration options

Usage Guides

See more usage examples

Build docs developers (and LLMs) love