Do the Web Form V14 allow print work?

Does the allow print option work for webforms, if so how do you download the print from the webform?

Yes, please check it.

Please check it.

Thank You!

Hi thanks, i found out how to enabled it, but does it support allow print as guest? because I had to set it to require login for it to work. I am trying to allow guest user to be able to print after submit.

with the guest user, we didn’t check so …

Hello,

I am also trying to print the form after submit.

Guest User should get option to download pdf of submitted form.

May I know any link or hint how to do it?

As of now I am getting this Submitted Message.

image

1 Like

Hello
have you figured out a solution for a guest to print a web form?

BRs

Hi there!

I would also need a way to do this.

Did anyone manage to make a flow which allows public people (not registered users) to either download or print the filled form?

preferably to have the redirected to a custom webpage made in the website Builder and have 2 buttons for print and pdf download.

would this be possible?

Since no one bothers to come with an answer, I will provide you with my fix, just in case someone else will need it:

Project Summary: Print/Download PDF Functionality in Frappe

We created a custom page in Frappe Builder that allows users to print or download the PDF of the latest generated document from a specific Doctype (Cerere Generala Rutiera), after a Webform submission. Below are the detailed steps, code, and full explanations.

The Goal was to have a simple web page with 2 buttons and allow logged in users to easily either print or download the PDF. Of course, you can choose the default print template from - Webform → Customize → Allow Print and choose the Template from there.

The API will retrieve the latest document the user generated, and replace the name dynamically in an API call (URL link).

1. Page Structure in Builder

The page created in Builder includes:

  1. Two buttons:
  • Print: Opens a print view in a new window.
  • Download PDF: Initiates the download of the document as a PDF.

2. JavaScript Script

Complete Script:

The script handles:

  • Fetching the latest document name using the backend API.
  • Configuring the buttons to generate dynamic links for printing and downloading.

Script:

document.addEventListener('DOMContentLoaded', function() {
    console.log('Page loaded, fetching the latest document...');

    // Retrieve CSRF token from Frappe
    const csrfToken = frappe.csrf_token;

    // Fetch API to get the name of the latest document
    fetch('/api/method/ghidul_cetateanului.api.get_latest_document_for_user', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Frappe-CSRF-Token': csrfToken, // Add CSRF Token
        },
        body: JSON.stringify({}) // Empty body, necessary for some POST requests
    })
    .then(response => response.json())
    .then(data => {
        if (data.message && data.message.status === "success") {
            const docName = data.message.document_name;
            console.log("Latest document:", docName);

            // Configure Print Button
            const printButton = document.getElementById('printButton');
            if (printButton) {
                printButton.textContent = 'Print'; // Default text
                printButton.addEventListener('click', function() {
                    printButton.textContent = 'Loading...'; // Loading text
                    printButton.disabled = true; // Disable button
                    const printUrl = '/printview?doctype=Cerere%20Generala%20Rutiera' +
                        '&name=' + encodeURIComponent(docName) +
                        '&format=Cerere%20Rutiera%20Standard' +
                        '&no_letterhead=1' +
                        '&trigger_print=1';

                    console.log('Opening print URL:', printUrl);
                    window.open(printUrl, '_blank');
                    printButton.textContent = 'Print'; // Restore text
                    printButton.disabled = false; // Re-enable button
                });
            }

            // Configure Download Button
            const downloadButton = document.getElementById('downloadButton');
            if (downloadButton) {
                downloadButton.textContent = 'Download PDF'; // Default text
                downloadButton.addEventListener('click', function() {
                    downloadButton.textContent = 'Downloading...'; // Loading text
                    downloadButton.disabled = true; // Disable button
                    const downloadUrl = '/api/method/frappe.utils.print_format.download_pdf?' +
                        'doctype=Cerere%20Generala%20Rutiera' +
                        '&name=' + encodeURIComponent(docName) +
                        '&format=Cerere%20Rutiera%20Standard' +
                        '&no_letterhead=1';

                    console.log('Opening download URL:', downloadUrl);
                    window.location.href = downloadUrl;
                    downloadButton.textContent = 'Download PDF'; // Restore text
                    downloadButton.disabled = false; // Re-enable button
                });
            }

            // Display success message
            const messageDiv = document.getElementById('statusMessage');
            if (messageDiv) {
                messageDiv.textContent = 'Document ready for printing/downloading: ' + docName;
                messageDiv.style.color = 'green';
            }
        } else {
            // Handle error if the document is not found
            const errorMessage = data.message ? data.message.message : "Could not find the document";
            console.error("Error:", errorMessage);
            alert('The recent document was not found. Please try again.');

            const messageDiv = document.getElementById('statusMessage');
            if (messageDiv) {
                messageDiv.textContent = errorMessage;
                messageDiv.style.color = 'red';
            }
        }
    })
    .catch(error => {
        // Handle network errors
        console.error('Error calling API:', error);
        alert('An error occurred while loading the document. Please reload the page.');

        const messageDiv = document.getElementById('statusMessage');
        if (messageDiv) {
            messageDiv.textContent = 'An error occurred. Please try again.';
            messageDiv.style.color = 'red';
        }
    });
});

3. How the Script Works

  1. Retrieve the latest document:
  • The script sends a POST request to the API to fetch the latest document for the logged-in user.
  • Includes a CSRF token for security.
  1. Configure buttons:
  • Print: Generates a link to open the print view in a new tab.
  • Download PDF: Generates a link to initiate the document download.
  1. Error handling:
  • Displays a status message if no document is found or if the API fails.
  1. Enhanced user experience:
  • Displays loading states and restores button text after actions are completed.

API Script in Backend

To complete the functionality, you need to define an API method in the Frappe backend. This method retrieves the name of the latest document from the specified Doctype ( In this case) (Cerere Generala Rutiera) for the logged-in user.

Complete API Script:

Add the following function to the api.py (create it in the console if there isn’t one) file in your app (In this case): (ghidul_cetateanului):

import frappe

@frappe.whitelist()
def get_latest_document_for_user():
    """
    Returns the latest document from 'Cerere Generala Rutiera' for the logged-in user.
    """
    try:
        # Get the logged-in user
        user = frappe.session.user

        # Get the latest document for the logged-in user
        doc = frappe.get_all(
            "Cerere Generala Rutiera",  # The Doctype to query
            fields=["name", "creation"],  # The fields to return
            filters={"owner": user},  # Filter by the logged-in user
            order_by="creation desc",  # Sort by creation date (descending)
            limit_page_length=1  # Return only one document
        )

        if doc:
            return {
                "status": "success",
                "document_name": doc[0]["name"],
                "creation": doc[0]["creation"]
            }
        else:
            return {"status": "error", "message": "No documents found for the current user"}

    except Exception as e:
        frappe.log_error(frappe.get_traceback(), "Error in get_latest_document_for_user")
        return {"status": "error", "message": str(e)}

Explanation of the API Script

  1. Necessary Imports:
  • frappe: Used to access Frappe methods and data.
  1. Retrieve the Logged-in User:
  • frappe.session.user gets the currently logged-in user.
  1. Fetch the Latest Document:
  • frappe.get_all: Fetches documents from a Doctype with options such as fields, filters, sorting, and limits.
  1. Handle Success:
  • If a document exists, it returns status: success along with the document’s name and creation date.
  1. Handle Errors:
  • If no documents are found or an exception occurs, the method returns status: error with the error message.
  • Errors are logged on the server using frappe.log_error.

Register the API

Ensure that the ghidul_cetateanului app is installed and functional:

bench --site your_site_name install-app ghidul_cetateanului

Ensure the method is accessible via API by decorating it with @frappe.whitelist().

Testing the API
a. Test from the System Console

Access the System Console in Frappe and run:

from ghidul_cetateanului.api import get_latest_document_for_user
print(get_latest_document_for_user())

b. Test from the Browser

Use the browser console to make a call using frappe.call:

frappe.call({
method: “ghidul_cetateanului.api.get_latest_document_for_user”,
callback: function(response) {
console.log(response.message);
}
});

c. Test with cURL

You can use cURL to verify the API functionality:

curl -X POST https://weave.ro/api/method/ghidul_cetateanului.api.get_latest_document_for_user
-H “Authorization: token your_api_key:your_api_secret”
-H “Content-Type: application/json”

Expected Result
On Success:

{
“status”: “success”,
“document_name”: “Numere Rosii - 01140136”,
“creation”: “2025-01-14 12:34:56”
}

On Error:

{
“status”: “error”,
“message”: “No documents found for the current user”
}

1 Like