V3 barcodes

V3 barcodes

The fliplet-barcode package does two things in a V3 app, both the same on web and native: it scans QR codes and barcodes with Fliplet.Barcode.attachScanner(), and it generates QR code and barcode images with Fliplet.Barcode.encode().

Scanning uses attachScanner() — a UI-less scanner you drive into a container element inside your own screen. It runs everywhere a V3 app runs (slug-hosted web, the Studio preview, and the native shell). You build the scanning UI yourself, the same way you build a login screen on top of Fliplet.Session; the API owns only the camera and the decoder.

This guide covers the recommended embedded-scanner pattern, a full worked example, the controller and options, camera permissions, and generating barcode images.

Prerequisites

Add the fliplet-barcode package to the screen, then load it before use:

await Fliplet.require.lazy.chain('fliplet-barcode');

Once the package is loaded, Fliplet.Barcode exposes two methods, both of which work the same on web and native: attachScanner() (scan, documented below) and encode() (generate a QR code or barcode image, documented under Generating barcodes).

attachScanner() has no built-in UI. You place and style a container element; attachScanner() runs the camera and decoder into it and calls you back on each successful decode. Because there is no platform-specific overlay, the same code works on web and native.

// Your screen owns this element and its styling:
// <div id="reader" style="width: 100%; max-width: 320px; aspect-ratio: 1;"></div>

const scanner = Fliplet.Barcode.attachScanner(document.getElementById('reader'), {
  onScan(result) {
    // result.text   — the decoded value, e.g. "https://example.com" or "5012345678900"
    // result.format — the symbology, e.g. "QR_CODE", "CODE_128", "EAN_13"
    scanner.stop(); // one-shot: stop after the first hit (omit to keep scanning)
    showResult(result.text);
  },
  onError(error) {
    // Fatal start error: camera permission denied, no camera, or library load failure.
    showMessage('Could not start the scanner. Check camera permissions and try again.');
  }
});

// Stop the camera when the user leaves the screen or closes your scanner UI:
scanner.stop();

Worked example: tap a button to scan

A typical scanning screen keeps the viewfinder hidden until the user asks for it, scans once, then shows the result. This is the whole flow in vanilla JS:

<button id="scan-btn">Scan a barcode</button>
<div id="reader" hidden style="width: 100%; max-width: 320px; aspect-ratio: 1; margin-top: 16px;"></div>
<p id="result"></p>
await Fliplet.require.lazy.chain('fliplet-barcode');

const btn = document.getElementById('scan-btn');
const reader = document.getElementById('reader');
const resultEl = document.getElementById('result');
let scanner = null;

btn.addEventListener('click', function () {
  reader.hidden = false;
  scanner = Fliplet.Barcode.attachScanner(reader, {
    onScan(result) {
      resultEl.textContent = `${result.format}: ${result.text}`;
      scanner.stop();
      reader.hidden = true;
    },
    onError() {
      resultEl.textContent = 'Camera unavailable — check permissions.';
      reader.hidden = true;
    }
  });
});

Vue component

In a V3 Vue screen, start the scanner from a button handler and always stop it on unmount so the camera is released:

// Scanner.vue (runtime template — V3 single-file components run without a build step)
export default {
  data() {
    return { value: '', scanner: null };
  },
  methods: {
    async start() {
      await Fliplet.require.lazy.chain('fliplet-barcode');
      this.scanner = Fliplet.Barcode.attachScanner(this.$refs.reader, {
        onScan: (result) => {
          this.value = result.text;
          this.scanner.stop();
        },
        onError: () => { this.value = 'Camera unavailable.'; }
      });
    }
  },
  beforeUnmount() {
    if (this.scanner) {
      this.scanner.stop();
    }
  },
  template: `
    <div>
      <button @click="start">Scan</button>
      <div ref="reader" style="width: 100%; max-width: 320px; aspect-ratio: 1;"></div>
      <p v-if="value"></p>
    </div>
  `
};

Controller and options

attachScanner(element, options) returns a controller and accepts:

  • element (HTMLElement String) — the container to render the camera into (an element or its id). You own its placement and styling; attachScanner() neither creates nor removes it.
  • options.onScan (Function) — called on every successful decode with { text, format }. Call controller.stop() inside it for one-shot scanning.
  • options.onError (Function) — called on a fatal start error (permission denied, no camera, or library load failure). Per-frame decode misses are not errors and are ignored.
  • options.fps (Number) — decode attempts per second. Default 10.
  • options.qrbox (Object Function) — scan-box size. Defaults to a centered square at 70% of the smaller edge.

The controller is { stop() }. stop() ends the camera, tears down the decoder (your element stays in the DOM), and returns a Promise.

Camera permissions

  • Web — the browser prompts for camera access when scanning starts, and getUserMedia requires a secure context (HTTPS). In the Studio preview the app runs in an iframe that already delegates camera; a published slug is served over HTTPS.
  • Native — the OS prompts on first use.

Handle a denied permission in onError — show the user how to re-enable the camera rather than leaving an empty viewfinder.

Generating barcodes

To render a QR code or barcode image, use Fliplet.Barcode.encode(). It works on web and native, returns the image as a Base64 string, and defaults to a QR code unless you pass a different format. You place the returned image in your own UI — the same “you own the UI” model as attachScanner() — for example into an <img> src, or save it with Fliplet.Media.

Fliplet.Barcode.encode()

Encode text into a QR code or barcode and resolve with the image as a Base64 string.

await Fliplet.require.lazy.chain('fliplet-barcode');

// QR code (default)
Fliplet.Barcode.encode('https://example.com').then(function (data) {
  document.getElementById('qr').src = data; // <img id="qr">
});

// Barcode with options
Fliplet.Barcode.encode('5012345678900', { format: 'ean13' }).then(function (data) {
  document.getElementById('code').src = data;
});
  • text (String) — the value to encode.
  • options (Object)
    • format (String) — qr (default), or barcode (encodes as code128), or a specific symbology: code39, code128, code128A, code128B, code128C, ean13, ean8, ean5, ean2, upc, upce, itf14, itf, msi, msi10, msi11, msi1010, msi1110, pharmacode, codabar, genericbarcode.
    • color (String) — foreground color, keyword (green) or hex (#00ff00). Default #000000.
    • background (String) — background color, keyword or hex. Default #ffffff.
    • width (Number) — QR code only. Width of the QR image. Default 600. (Barcode width is driven by the text length and lineWidth.)
    • height (Number) — height of the image. Default 600 for QR, 150 for barcode.
    • lineWidth (Number) — barcode only. Width of a single bar; larger values produce a wider image. Default 2.

Tip: QR codes are always 1:1, so they scale cleanly. Prefer a QR code unless a linear barcode is specifically required; for barcodes, tune height and lineWidth to the length of the encoded text. encode() returns the raw image and renders no UI of its own — display it however your screen needs.

Patterns — DO and DON’T

DO

  • Build your own scanning UI (button, viewfinder container, result area) and drive attachScanner() into it.
  • Call controller.stop() after the first scan for one-shot flows, and on screen teardown/unmount to release the camera.
  • Handle onError with a user-facing message about camera permissions.
  • Give the container an explicit size — the camera fills it.

DON’T

  • Don’t leave the scanner running after navigation — a live camera drains battery and blocks other capture.
  • Don’t add a separate “scanner” package or a custom camera/getUserMedia stack — attachScanner() is the supported cross-platform scanner.
  • V3 routing — base-path and navigation patterns for the screen that hosts your scanner.