Utilizzo dell'API DModal per rendere finestre modali (aka popup/dialoghi) in Discourse

Discourse 3.1.0.beta6 include una nuova API basata su componenti <DModal>.

:information_source: Questa sostituisce la vecchia API basata sui controller, che ora è deprecata. Se hai modali esistenti che utilizzano le vecchie API, consulta la guida alla migrazione qui.

Rendering di un Modale

I modali vengono renderizzati includendo il componente <DModal> in un template Handlebars. Se non hai già un template adatto, consulta Using Plugin Outlet Connectors from a Theme or Plugin.

Un modale semplice potrebbe assomigliare a questo:

<DButton
  @translatedLabel="Mostra Modale"
  @action={{fn (mut this.modalIsVisible) true}}
/>

{{#if this.modalIsVisible}}
  <DModal @title="Il Mio Modale" @closeModal={{fn (mut this.modalIsVisible) false}}>
    Ciao mondo, questo è un contenuto all'interno di un modale
  </DModal>
{{/if}}

:information_source: L’helper mut viene utilizzato qui come modo specifico per hbs per impostare un valore. Potresti anche impostare modalIsVisible utilizzando qualsiasi altro metodo standard di Ember.

Questo esempio creerà un modale semplice come questo:

Incapsulamento in un componente

Prima di introdurre ulteriori complessità, è generalmente meglio incapsulare il tuo nuovo Modale nella definizione del proprio Componente. Spostiamo il contenuto di <DModal> all’interno di un nuovo componente <MyModal />

// components/my-modal.gjs
<template>
  <DModal @title="Il Mio Modale" @closeModal={{@closeModal}}>
    Ciao mondo, questo è un contenuto all'interno di un modale
  </DModal>
</template>

Aggiornare questo file .gjs a un componente basato su classi ti permetterà di introdurre logica e stato più complessi.

Per utilizzare il nuovo componente, aggiorna il punto di chiamata per farvi riferimento, assicurandoti di passare un argomento @closeModal.

<DButton
  @translatedLabel="Mostra Modale"
  @action={{fn (mut this.modalIsVisible) true}}
/>

{{#if this.modalIsVisible}}
  <MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}

Aggiunta di un piè di pagina

Molti modali includono una qualche forma di invito all’azione. In Discourse, questi tendono a essere posizionati nella parte inferiore del modale. Per rendere possibile ciò, DModal dispone di diversi «blocchi con nome» nei quali è possibile renderizzare contenuto. Ecco l’esempio aggiornato per includere due pulsanti nel piè di pagina, uno dei quali è il nostro pulsante standard DModalCancel

<DModal @title="Il Mio Modale" @closeModal={{@closeModal}}>
  <:body>
    Ciao mondo, questo è un contenuto all'interno di un modale
  </:body>
  <:footer>
    <DButton class="btn-primary" @translatedLabel="Invia" />
    <DModalCancel @close={{@closeModal}} />
  </:footer>
</DModal>

Rendering di un modale da un contesto non hbs

Idealmente, le istanze di <DModal> dovrebbero essere renderizzate all’interno di un template Ember utilizzando la tecnica dichiarativa dimostrata sopra. Se ciò non è fattibile per il tuo caso d’uso, può essere fatto iniettando il servizio modal e chiamando modal.show().

Assicurati di aver incapsulato il tuo modale nel proprio componente come descritto sopra. Quindi, attiva il modale passando un riferimento alla tua classe di componente a showModal:

import MyModal from "discourse/components/my-modal";

// (inietta il servizio modal nel luogo appropriato)

// Aggiungi questa chiamata ogni volta che vuoi aprire il modale.
// Un argomento `@closeModal` verrà passato automaticamente al tuo componente.
this.modal.show(MyModal);

// Opzionalmente, passa un parametro `model`. Passato come `@model` al tuo componente.
// Questo può includere dati e anche azioni/callback per l'uso del tuo Modale.
this.modal.show(MyModal, {
  model: { topic: this.topic, someAction: this.someAction },
});

// `modal.show()` restituisce una promise, quindi puoi attendere che venga chiuso
// Si risolverà con i dati passati all'azione `@closeModal`
const result = await this.modal.show(MyModal);

Ancora più personalizzabilità!

<DModal> dispone di diversi blocchi con nome e argomenti.

Argomenti

Argomento Scopo
@closeModal Richiesto affinché l’interfaccia di chiusura appaia.
@title Renderizza <h1 id="discourse-modal-title">; imposta aria-labelledby.
@subtitle Testo piccolo sotto il titolo.
@flash / @flashType Avviso inline nella parte superiore del modale (DFlashMessage).
@hideHeader, @hideFooter Nascondi intere aree.
@headerClass, @bodyClass Classe aggiuntiva sui wrapper dell’header/body.
@dismissable Default true quando @closeModal è impostato. Disabilita Esc / click sullo sfondo / X.
@autofocus Default true. Mette a fuoco automaticamente il primo elemento focusabile tramite dTrapTab.
@submitOnEnter Default true. Invio clicca .d-modal__footer .btn-primary a meno che il focus non sia in un form / textarea / select-kit.
@beforeClose async ({ initiatedBy }) => boolean. Restituisci false per annullare la chiusura (es. conferma form non salvato).
@hidden Sospende la gestione della tastiera; utilizzato quando un modale annidato è in primo piano.
@tagName "div" (default) o "form". Usa "form" per i form in modo che il submit nativo funzioni.

Blocchi

Blocco Posizione Quando utilizzarlo
default / :body Area del contenuto principale Area predefinita
:aboveHeader In alto, prima dell’header Raramente necessario; per contenuti che devono trovarsi sopra la barra del titolo (es. un banner).
:headerAboveTitle All’interno dell’header, prima del titolo Presente ma non utilizzato. Raramente necessario.
:belowModalTitle All’interno di .d-modal__title, dopo il <h1> Posizione eccellente per metadati supplementari.
:headerBelowTitle All’interno dell’header, dopo il blocco del titolo Schede, sotto-navigazione o campo di ricerca che fanno parte dell’header.
:headerPrimaryAction Lato destro dell’header solo su mobile Sostituisce il pulsante di chiusura X con un’azione primaria (es. «Salva»). Genera anche automaticamente un pulsante «Annulla» a sinistra e aggiunge .--has-primary-action all’header.
:belowHeader Tra header e body Contenuto di sotto-header persistente (es. ricerca) che si trova fuori dal corpo scorrevole, quindi visualizzazione fissa.
:aboveFooter Tra body e footer Soppresso quando @hideFooter è impostato. Utilizzare per contenuti legati al footer ma esterni ad esso. Anche questo è raro.
:footer Barra delle azioni inferiore Pulsanti primari e secondari. Il primo .btn-primary qui è ciò che viene attivato da Invio.
:belowFooter Dopo il footer Raramente necessario; ignora @hideFooter. Utile per testo di stato esterno all’area del footer bordata.

Fonti: la guida allo stile interattiva per gli argomenti, e l’implementazione del template d-modal per i blocchi con nome.

CSS

Utilizza le classi .d-modal come punto di riferimento per sovrascrivere il core ed evita il selettore legacy .modal.

4 modificatori disponibili:

  • .--large imposta la larghezza massima a 800px (solo desktop)
  • .--max imposta la larghezza massima a 90vw (solo desktop)
  • .has-search imposta l’altezza fissa (80vh): inteso per modali con sistema di ricerca/filtro per evitare cambiamenti di altezza in base alla lunghezza dei risultati (solo desktop)
  • .--stacked imposta i pulsanti del footer in impilamento (solo mobile)

Questo documento è sottoposto a controllo versione: suggerisci modifiche su github.

17 Mi Piace

Un post è stato diviso in un nuovo argomento: Posso mostrare una modale da head_tag