---
suivi: 1278
date: 2026-08-11
sujet: Depot Show — plantage rendu Vue (insertBefore)
chantier: depot-factures
type: fix
statut: poussé
hash: 7a79edf8
fichiers:
  - resources/js/Pages/DepotFactures/DepotFactureSaisieForm.vue
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1278_depot_show_plantage_rendu.md
---

# SUIVI #1278 — Plantage de rendu sur `DepotFactures/Show`

## PROMPT ENVOYÉ

Fix front. Console Show (Lahouari / dépôt 1230) : `insertBefore` sur `null` + `emitsOptions` sur `null`. CIE `loading` figé au-delà du timeout #1277. Endpoint dues OK. Ne pas toucher AppShell / Show / Index si possible. Filet `onErrorCaptured` obligatoire.

## OBJET 1 — Analyse

### a) Teleports dans `DepotFactureSaisieForm.vue`

| # | Cible | Avant #1278 | Index | Show |
|---|---|---|---|---|
| 1 | `#depot-saisie-subnav-host` (AppShell, `v-if` Index\|Show) | Toujours monté ; `:disabled="!depotSubnavHostReady"` puis enable après `onMounted` ; contenu `v-if="showStickySaisieHeader && host"` | Hôte **oui** (composant Index). Sticky **oui** si `!readonly`. | Hôte **oui** (composant Show). Sticky **non** si `externalWorkflowActions` (parcours NV1). Teleport **quand même activé** avec enfants vides. |
| 2 | `#compta-saisie-header-actions` (page Comptabilisation) | Toujours monté ; `:disabled="!comptabilisationMode"` | Cible **absente**. disabled=true. | Idem — cible **absente**. |

Composants enfants montés (`ActionBar`, `ObjectSubNavBar`, `DocumentsJointsPanel`, `ProgrammeSearchSelect`, dialogs) : **aucun** autre Teleport.

### b) Disponibilité hôte

- AppShell pose `#depot-saisie-subnav-host` si `page.component` ∈ {`DepotFactures/Index`, `DepotFactures/Show`} — présent dès le layout, avant/avec le mount du form.
- `#compta-saisie-header-actions` : uniquement `Factures/Comptabilisation/Index`.

### c) Autres candidats

| Candidat | Verdict |
|---|---|
| `v-if`/`v-for` même nœud | **écarté** — clés distinctes sur listes CIE |
| `key` manquante CIE | **écarté** — `:key="ligne.repartition_id"` |
| demontage pendant `await` dues | **secondaire** — n’explique pas `insertBefore` moteur |
| MutationObserver #1271 | **contributeur possible** (mutation DOM sync pendant patch) — durci en rAF, pas cause primaire |
| Splitter PrimeVue (Show only) | **écarté comme cause primaire** — ne déplace pas les nœuds enfants hors de Vue ; resize styles only |
| Manipulation DOM hors Vue | **écarté** hors title tooltips |

### d) CAUSE RETENUE (preuve)

**Structure Teleport #1270** :

1. Teleport **toujours** présent dans le template.
2. Après `onMounted`, `depotSubnavHostReady=true` → `:disabled` passe de `true` à `false` → Vue exécute `moveTeleport` (disabled→enabled).
3. Sur **Show** NV1 : `showStickySaisieHeader===false` (car `externalWorkflowActions`) → enfants conditionnels **absents**, mais le Teleport s’active quand même vers l’hôte.
4. Teleport #2 pointe en permanence vers une cible **inexistante** sur Index/Show (même disabled) — footgun documenté Vue (#11230 / hydratation / updates).

Preuve d’alignement avec le symptôme :

- Erreurs = moteur de rendu (`insertBefore` / `emitsOptions`), pas HTTP CIE.
- Timeout 20s #1277 **ne mettait pas à jour l’UI** si le scheduler de patch était cassé → `loading` éternel malgré endpoint 200.
- Index validé 16 lots ; Show jamais : seul Show active le Teleport Ariane **sans** contenu sticky tout en ayant l’hôte + barre native séparée.

## OBJET 2 — Correctif

- Teleport Ariane : monté **seulement** si `showStickySaisieHeader` **et** hôte présent ; sinon header local (fallback réel).
- Sur Show workflow : **aucun** Teleport Ariane → pas de doublon avec la barre Show.
- Teleport compta : monté **seulement** si `comptabilisationMode` **et** hôte présent.

### Doublons boutons

| Écran | Boutons Show natifs | Boutons Teleport form | Doublon |
|---|---|---|---|
| Show + `externalWorkflowActions` | oui (Retour, NV1, Enregistrer, Valider, …) | non (`showStickySaisieHeader=false`) | **non** |
| Index saisie éditable | non | oui (sous Ariane si hôte) | **non** |
| Show sans workflow header | non (ou partiel) | oui si sticky | **non** |

`AppShell.vue` / `Show.vue` / `Index.vue` : **non modifiés**.

## OBJET 3 — Filet

- `onErrorCaptured` → `cieDuesLoading=false`, phase `error`, message `erreur de rendu : …` visible.
- Timeout 20s : pose explicitement `phase=error` / motif timeout même sur abort.
- Motif CIE distingue rendu / timeout / HTTP.

## OBJET 4 — Props Index vs Show

| Prop | Index | Show |
|---|---|---|
| `use-ajax` | `true` | `false` |
| `readonly` | `can_edit === false` | `!(can_edit ?? depot.can_edit)` |
| `external-workflow-actions` | défaut `false` | `showWorkflowHeader` |
| `comptabilisationMode` | défaut `false` | défaut `false` |
| payload props | via `saisiePayload` ajax | `v-bind="props"` page |

| Acquis | Index | Show |
|---|---|---|
| Boutons sous Ariane (#1270) | **oui** (Teleport) | **non** (barre native Show — voulu) |
| Cartes espacées (#1272) | oui (même form) | oui si rendu OK |
| Totaux « Montant à comptabiliser » | oui | oui si rendu OK |
| Selects + infobulle (#1271) | oui | oui (observer durci) |
| Lignes CIE #1268 | oui | oui si rendu OK |
| Case CIE `modifiable` serveur #1277 | oui | oui si rendu OK |

Acquis qui ne tient **que** sur Index par design : emplacement Teleport sous Ariane (#1270). Show conserve sa barre native — hors périmètre de « corriger » vers Ariane.

## LEÇON

Un composant monté dans **deux** écrans doit être validé sur les **deux**. 16 lots (#1264–#1277) n’ont été joués que sur `Index` : le Teleport #1270 a cassé `Show` sans être vu. Un `loading` qui survit au timeout est un symptôme de **rendu mort**, pas d’API.

## DÉPLOIEMENT-TEST

```
git pull origin main
php artisan optimize:clear
php artisan view:clear
php artisan journal:sync
```

Vérification agent : **lecture de code uniquement** (pas d’écran réel Index/Show).
