Utilizzare i chip con elenco a discesa

L'API Google Docs ti consente di creare, inserire, aggiornare, leggere e gestire in modo programmatico i chip con elenco a discesa all'interno dei documenti Google Docs.

Che cosa sono i chip con elenco a discesa?

I chip con elenco a discesa in Documenti Google offrono agli utenti un menu di selezione interattivo e personalizzabile in linea con il testo del documento. Gli utenti possono fare clic su un chip con elenco a discesa per selezionare da un elenco predefinito di opzioni, ognuna con il proprio testo visualizzato e stile di colore. I chip con elenco a discesa vengono spesso utilizzati per il monitoraggio dei progetti, gli aggiornamenti di stato, i flussi di lavoro di revisione e le fasi di approvazione.

Tramite l'API Documenti, puoi:

  • Definisci modelli di menu a discesa riutilizzabili con titoli, nomi delle opzioni e colori personalizzati.
  • Inserisci i chip con elenco a discesa in una posizione valida per i caratteri.
  • Aggiorna l'opzione selezionata di una singola istanza di chip con elenco a discesa.
  • Modifica le definizioni dei menu a discesa condivisi in linea, aggiornando contemporaneamente tutti i chip di riferimento.
  • Sostituisci o ritira in sicurezza le opzioni mantenendo l'integrità referenziale nei chip esistenti.
  • Elimina i modelli di menu a discesa inutilizzati.

Architettura: definizioni e istanze

Nell'API Docs, i chip con elenco a discesa hanno definizioni e istanze. Una definizione imposta le opzioni per un'istanza del menu a discesa. Un'istanza di menu a discesa è un menu a discesa con cui le persone possono interagire e che salva le informazioni sulle selezioni.

L'API Docs separa la configurazione del modello di menu a discesa dalle istanze di chip con elenco a discesa incorporato:

  1. DropdownDefinition: un modello a livello di scheda che definisce il titolo del menu a discesa e la raccolta di scelte selezionabili (DropdownOption). Non si trova in un offset di caratteri specifico nel documento, ma viene memorizzato nella mappa di definizione della scheda: document.tabs[].documentTab.dropdownDefinitions.
  2. Menu a discesa: una singola istanza di chip incorporata in linea all'interno di un elemento paragrafo (ParagraphElement.dropdown). Ogni istanza di menu a discesa fa riferimento a un dropdownDefinitionId e memorizza il proprio selectedOptionId attivo.

La modifica di un DropdownDefinition (ad es. l'aggiunta di un'opzione o la ridenominazione del titolo) aggiorna tutti i chip di riferimento nella scheda senza richiedere aggiornamenti a ogni singolo elemento.

Ogni istanza di Dropdown tiene traccia del proprio selectedOptionId. La modifica del valore selezionato di un singolo chip influisce solo su quella specifica istanza.

Regole di convalida e formato dell'ID

Gli ID forniti dagli utenti devono rispettare specifiche rigorose in termini di formato, prefisso e lunghezza:

Identificatore Prefisso obbligatorio Espressione regolare di convalida Limite di lunghezza Esempio
ID definizione menu a discesa (dropdownDefinitionId) kix. ^kix\.[a-zA-Z0-9_-]{2,14}$ 6-18 caratteri kix.review_status
ID opzione menu a discesa (optionId) dropdownItem. ^dropdownItem\.[a-zA-Z0-9_-]{2,14}$ 15-27 caratteri dropdownItem.pending

Generare ID forniti dall'utente

Per generare ID che rispettino i requisiti obbligatori relativi al prefisso e all'espressione regolare, utilizza le seguenti funzioni helper. Questi helper generano suffissi alfanumerici in base 36 minuscoli, corrispondenti al formato generato dall'interfaccia utente di Documenti Google:

Python

import random
import string

def generate_dropdown_definition_id(suffix_len: int = 8) -> str:
    """Generates a valid user-provided DropdownDefinition ID (6-18 chars, starting with 'kix.')."""
    chars = string.ascii_lowercase + string.digits
    suffix = "".join(random.choices(chars, k=max(2, min(suffix_len, 14))))
    return f"kix.{suffix}"

def generate_dropdown_option_id(suffix_len: int = 8) -> str:
    """Generates a valid user-provided DropdownOption ID (15-27 chars, starting with 'dropdownItem.')."""
    chars = string.ascii_lowercase + string.digits
    suffix = "".join(random.choices(chars, k=max(2, min(suffix_len, 14))))
    return f"dropdownItem.{suffix}"

Java

import java.security.SecureRandom;

public final class DropdownIdGenerator {
  private static final String BASE36_CHARS =
      "abcdefghijklmnopqrstuvwxyz0123456789";
  private static final SecureRandom RANDOM = new SecureRandom();

  private DropdownIdGenerator() {}

  /** Generates a valid user-provided DropdownDefinition ID (6-18 chars, starting with "kix."). */
  public static String generateDefinitionId(int suffixLength) {
    int length = Math.max(2, Math.min(suffixLength, 14));
    StringBuilder sb = new StringBuilder("kix.");
    for (int i = 0; i < length; i++) {
      sb.append(BASE36_CHARS.charAt(RANDOM.nextInt(BASE36_CHARS.length())));
    }
    return sb.toString();
  }

  /** Generates a valid user-provided DropdownOption ID (15-27 chars, starting with "dropdownItem."). */
  public static String generateOptionId(int suffixLength) {
    int length = Math.max(2, Math.min(suffixLength, 14));
    StringBuilder sb = new StringBuilder("dropdownItem.");
    for (int i = 0; i < length; i++) {
      sb.append(BASE36_CHARS.charAt(RANDOM.nextInt(BASE36_CHARS.length())));
    }
    return sb.toString();
  }
}

Creare e inserire chip con elenco a discesa

Creazione di un singolo batch (consigliata)

Il pattern più efficiente combina CreateDropdownDefinitionRequest e InsertDropdownRequest in una singola chiamata documents.batchUpdate.

Il seguente esempio di codice crea una definizione del menu a discesa "Stato revisione" con tre scelte codificate a colori utilizzando gli ID forniti dall'utente e inserisce un'istanza alla fine del documento:

Python

requests = [
    {
        "createDropdownDefinition": {
            "dropdownDefinition": {
                "dropdownDefinitionId": "kix.review_status",
                "dropdownDefinitionProperties": {
                    "title": "Review Status",
                    "options": [
                        {
                            "optionId": "dropdownItem.pending",
                            "displayValue": "Pending Review",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.99, "green": 0.90, "blue": 0.65}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.45, "green": 0.30, "blue": 0.0}}
                                },
                            },
                        },
                        {
                            "optionId": "dropdownItem.approved",
                            "displayValue": "Approved",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.85, "green": 0.95, "blue": 0.85}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.08, "green": 0.40, "blue": 0.15}}
                                },
                            },
                        },
                        {
                            "optionId": "dropdownItem.rejected",
                            "displayValue": "Needs Changes",
                            "textStyle": {
                                "backgroundColor": {
                                    "color": {"rgbColor": {"red": 0.98, "green": 0.84, "blue": 0.84}}
                                },
                                "foregroundColor": {
                                    "color": {"rgbColor": {"red": 0.65, "green": 0.10, "blue": 0.10}}
                                },
                            },
                        },
                    ],
                },
            }
        }
    },
    {
        "insertDropdown": {
            "endOfSegmentLocation": {},
            "dropdownDefinitionId": "kix.review_status",
            "selectedOptionId": "dropdownItem.pending",
        }
    },
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();

List<DropdownOption> options = Arrays.asList(
    new DropdownOption()
        .setOptionId("dropdownItem.pending")
        .setDisplayValue("Pending Review")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.99f).setGreen(0.90f).setBlue(0.65f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.45f).setGreen(0.30f).setBlue(0.0f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.approved")
        .setDisplayValue("Approved")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.85f).setGreen(0.95f).setBlue(0.85f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.08f).setGreen(0.40f).setBlue(0.15f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.rejected")
        .setDisplayValue("Needs Changes")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.98f).setGreen(0.84f).setBlue(0.84f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.65f).setGreen(0.10f).setBlue(0.10f))))));

DropdownDefinition definition = new DropdownDefinition()
    .setDropdownDefinitionId("kix.review_status")
    .setDropdownDefinitionProperties(new DropdownDefinitionProperties()
        .setTitle("Review Status")
        .setOptions(options));

requests.add(new Request().setCreateDropdownDefinition(
    new CreateDropdownDefinitionRequest().setDropdownDefinition(definition)));

requests.add(new Request().setInsertDropdown(
    new InsertDropdownRequest()
        .setEndOfSegmentLocation(new EndOfSegmentLocation())
        .setDropdownDefinitionId("kix.review_status")
        .setSelectedOptionId("dropdownItem.pending")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

Regole di convalida e limiti dei menu a discesa

Quando crei o modifichi le definizioni dei menu a discesa, si applicano i seguenti vincoli:

  • Conteggio opzioni: una definizione di menu a discesa deve avere un numero di opzioni compreso tra 2 e 50.
  • Lunghezza titolo: la definizione title non può essere vuota e non deve superare i 200 caratteri.
  • Lunghezza valore visualizzato: il displayValue di ogni opzione non può essere vuoto e non deve superare i 200 caratteri.
  • Stile opzione: in DropdownOption.textStyle sono supportati solo foregroundColor e backgroundColor. L'impostazione di altre proprietà di stile restituisce un errore 400 Bad Request.
  • Selezione predefinita: in InsertDropdownRequest, se selectedOptionId viene omesso, il chip viene impostato per impostazione predefinita sulla prima opzione definita in DropdownDefinition.

Aggiornare la selezione di un singolo chip con elenco a discesa

Per modificare l'opzione selezionata di un'istanza di chip con elenco a discesa esistente senza alterare il modello o altri chip, utilizza UpdateDropdownPropertiesRequest:

  • dropdownId: (obbligatorio) l'ID dell'istanza specifica del chip con elenco a discesa da aggiornare.
  • tabId: l'ID della scheda contenente il menu a discesa (per impostazione predefinita, la prima scheda se omesso).
  • fields: impostato su "selectedOptionId".

Il seguente esempio di codice aggiorna la selezione attiva di un chip con elenco a discesa a "dropdownItem.approved":

Python

requests = [
    {
        "updateDropdownProperties": {
            "dropdownId": "kix.chip_abc1",
            "tabId": "t.0",
            "dropdownProperties": {
                "selectedOptionId": "dropdownItem.approved",
            },
            "fields": "selectedOptionId",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();
requests.add(new Request().setUpdateDropdownProperties(
    new UpdateDropdownPropertiesRequest()
        .setDropdownId("kix.chip_abc1")
        .setTabId("t.0")
        .setDropdownProperties(new DropdownProperties()
            .setSelectedOptionId("dropdownItem.approved"))
        .setFields("selectedOptionId")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

Aggiornare le definizioni e le opzioni dei menu a discesa

Per modificare il modello stesso (titolo, elenco delle opzioni, etichette di visualizzazione o colori), utilizza UpdateDropdownDefinitionPropertiesRequest. L'aggiornamento di una definizione aggiorna automaticamente tutti i chip con elenco a discesa che la fanno riferimento nella scheda.

Sostituzione dell'elenco completo per le opzioni

Quando dropdownDefinitionProperties.options è incluso nella maschera fields, la richiesta esegue una sostituzione dell'elenco completo. Devi fornire l'elenco completo delle opzioni nell'ordine scelto. Il server confronta l'elenco in entrata con la definizione attuale:

  • Nuova opzione: l'inclusione di un'opzione senza optionId (o con un nuovo optionId fornito dall'utente) la aggiunge alla definizione.
  • Opzione aggiornata: se fornisci un optionId esistente con aggiornamenti displayValue o textStyle modificati, l'opzione viene aggiornata.
  • Opzioni riordinate: l'elenco delle opzioni viene salvato nella sequenza esatta fornita nella richiesta.
  • Opzione eliminata: l'omissione di un optionId esistente elimina l'opzione dalla definizione.

Integrità referenziale e sostituzione delle opzioni

Se un'opzione da eliminare è selezionata in un chip con elenco a discesa all'interno del documento, devi fornire una mappatura in selectedOptionIdReplacements (map<string, string>). Le chiavi sono gli ID delle opzioni da eliminare e i valori sono gli ID delle opzioni di sostituzione.

Il seguente esempio di codice mostra come aggiornare una definizione di menu a discesa con sostituzioni di opzioni:

Python

requests = [
    {
        "updateDropdownDefinitionProperties": {
            "dropdownDefinitionId": "kix.review_status",
            "tabId": "t.0",
            "dropdownDefinitionProperties": {
                "title": "Editorial Review Status",
                "options": [
                    {
                        "optionId": "dropdownItem.approved",
                        "displayValue": "Approved",
                        "textStyle": {
                            "backgroundColor": {
                                "color": {"rgbColor": {"red": 0.85, "green": 0.95, "blue": 0.85}}
                            },
                            "foregroundColor": {
                                "color": {"rgbColor": {"red": 0.08, "green": 0.40, "blue": 0.15}}
                            },
                        },
                    },
                    {
                        "optionId": "dropdownItem.rejected",
                        "displayValue": "Changes Requested",
                        "textStyle": {
                            "backgroundColor": {
                                "color": {"rgbColor": {"red": 0.98, "green": 0.84, "blue": 0.84}}
                            },
                            "foregroundColor": {
                                "color": {"rgbColor": {"red": 0.65, "green": 0.10, "blue": 0.10}}
                            },
                        },
                    },
                ],
            },
            "selectedOptionIdReplacements": {
                "dropdownItem.pending": "dropdownItem.rejected"
            },
            "fields": "title,options",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<DropdownOption> updatedOptions = Arrays.asList(
    new DropdownOption()
        .setOptionId("dropdownItem.approved")
        .setDisplayValue("Approved")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.85f).setGreen(0.95f).setBlue(0.85f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.08f).setGreen(0.40f).setBlue(0.15f))))),
    new DropdownOption()
        .setOptionId("dropdownItem.rejected")
        .setDisplayValue("Changes Requested")
        .setTextStyle(new TextStyle()
            .setBackgroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.98f).setGreen(0.84f).setBlue(0.84f))))
            .setForegroundColor(new OptionalColor().setColor(
                new Color().setRgbColor(new RgbColor().setRed(0.65f).setGreen(0.10f).setBlue(0.10f))))));

Map<String, String> replacements = new HashMap<>();
replacements.put("dropdownItem.pending", "dropdownItem.rejected");

List<Request> requests = new ArrayList<>();
requests.add(new Request().setUpdateDropdownDefinitionProperties(
    new UpdateDropdownDefinitionPropertiesRequest()
        .setDropdownDefinitionId("kix.review_status")
        .setTabId("t.0")
        .setDropdownDefinitionProperties(new DropdownDefinitionProperties()
            .setTitle("Editorial Review Status")
            .setOptions(updatedOptions))
        .setSelectedOptionIdReplacements(replacements)
        .setFields("title,options")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

Eliminare una definizione del menu a discesa

Per rimuovere un modello di menu a discesa non utilizzato, utilizza DeleteDropdownDefinitionRequest.

Il seguente esempio di codice mostra come eliminare una definizione di menu a discesa:

Python

requests = [
    {
        "deleteDropdownDefinition": {
            "dropdownDefinitionId": "kix.review_status",
            "tabId": "t.0",
        }
    }
]

result = service.documents().batchUpdate(
    documentId=DOCUMENT_ID,
    body={"requests": requests}
).execute()

Java

List<Request> requests = new ArrayList<>();
requests.add(new Request().setDeleteDropdownDefinition(
    new DeleteDropdownDefinitionRequest()
        .setDropdownDefinitionId("kix.review_status")
        .setTabId("t.0")));

BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests);
BatchUpdateDocumentResponse response = docsService.documents()
    .batchUpdate(DOCUMENT_ID, body)
    .execute();

Gestione degli errori e risoluzione dei problemi

Condizioni di errore comuni e soluzioni:

Codice di stato Causa Risoluzione
400 INVALID_ARGUMENT Prefisso ID o formato dell'espressione regolare non valido. Assicurati che dropdownDefinitionId inizi con kix. (6-18 caratteri) e che optionId inizi con dropdownItem. (15-27 caratteri).
400 INVALID_ARGUMENT Il conteggio delle opzioni non rientra nei limiti. Una definizione di menu a discesa deve contenere un numero di opzioni compreso tra 2 e 50.
400 INVALID_ARGUMENT Il titolo o il valore visualizzato è vuoto o supera i 200 caratteri. Fornisci una stringa non vuota compresa tra 1 e 200 caratteri.
400 INVALID_ARGUMENT Proprietà dello stile di testo non supportata nell'opzione. Solo foregroundColor e backgroundColor sono supportati nelle opzioni del menu a discesa. Rimuovi il carattere, le dimensioni o altri attributi.
400 INVALID_ARGUMENT Mapping di sostituzione dell'opzione mancante durante l'eliminazione. Quando elimini un'opzione selezionata da un chip, fornisci una sostituzione valida in selectedOptionIdReplacements.
400 INVALID_ARGUMENT Tentativo di eliminare una definizione in uso. Elimina o riassegna il target di tutte le istanze di chip con elenco a discesa che fanno riferimento alla definizione prima di eliminarla.
400 INVALID_ARGUMENT ID fornito dall'utente duplicato. Assicurati che gli ID forniti dagli utenti siano univoci nella scheda del documento.