2016-03-04 19 views
8

Ho definito un elemento personalizzato e voglio eseguire uno script solo quando l'elemento personalizzato viene aggiornato al suo tipo registrato. Il caso d'uso è che devo chiamare un metodo personalizzato.Come eseguire uno script quando si aggiorna l'elemento personalizzato

mio file html principale appare così:

<project-list></project-list> 
<script> 
    var project_list = document.getElementsByTagName("project-list")[0] 
    project_list.custom_method("some_data"); 
</script> 

L'elemento personalizzato viene registrato nel un'importazione HTML come questo:

<script> 
    "use strict"; 
    var currentScript = document._currentScript || document.currentScript; 

    class ProjectList extends HTMLElement { 

    createdCallback(){ 
     console.log("created"); 
    } 

    custom_method(data) { 
     console.log("custom_method() OK"); 
     console.log(data); 

     this.innerHTML = data; 
    } 

    } 

    document.registerElement("project-list", ProjectList); 
</script> 

mia domanda è semplice: come assicurarsi lo script nel file html principale viene chiamato solo dopo che l'elemento personalizzato ottiene il suo metodo custom_method?

Sto cercando una soluzione elegante. Qualcosa a cui gli autori delle specifiche avrebbero pensato. Non mi interessa cambiare un po 'l'architettura (ad esempio spostando il javascript dal file principale in un altro elemento personalizzato, se necessario).

+1

sui browser che implementano le specifiche, creando l'elemento e accodandolo sarà sincronizzato. in termini di tag hard-coded però, afaik, non esiste un evento DOM "allComponentsReady". un modo è di aumentare un evento personalizzato su 'document' dal componente, e usare quell'evento come un evento' onload() 'per il codice della pagina che richiede i metodi personalizzati. potresti anche cercare in qualcosa di simile a ricollegare molti componenti web e metodi di app disparati in un modo che non fa schifo. – dandavis

+0

@dandavis: questo è quello che faccio. Ma ho anche impostato una bandiera. Se il flag è impostato, il componente è già impostato e il metodo personalizzato può essere eseguito immediatamente. Altrimenti, è pianificato per quando l'evento viene attivato. Ho inviato una risposta con il codice che uso. – MarcG

+0

@dandavis: per collegare molti componenti Web disparati: se alcuni componenti Web dipendono da altri, allora deve attendere che TUTTI questi altri componenti siano pronti, prima di impostare/inviare i propri flag/eventi. – MarcG

risposta

3

Sync HTML Import

Come suggerito da @dandavis, a causa del comportamento di default sync degli elementi <link> e <script>, è solo mettere i tag nel giusto ordine: iscrizione prima chiamata di metodo.

O invece è possibile chiamare il metodo personalizzato quando il DOMContentLoaded o l'evento window.onload è licenziato, come di seguito:

window.onload = function() 
 
{ 
 
    var project_list = document.getElementsByTagName("project-list")[0] 
 
    project_list.custom_method("some_data")  
 
}
<project-list></project-list> 
 

 
<script> 
 
    "use strict"; 
 
    var currentScript = document._currentScript || document.currentScript; 
 

 
    class ProjectList extends HTMLElement { 
 

 
    createdCallback(){ 
 
     console.log("created"); 
 
    } 
 

 
    custom_method(data) { 
 
     console.log("custom_method() OK"); 
 
     console.log(data); 
 

 
     this.innerHTML = data; 
 
    } 
 

 
    } 
 

 
    document.registerElement("project-list", ProjectList); 
 
</script>

Async HTML Import

Se per qualche motivi per cui vuoi caricare il tuo file di importazione HTML in modo asincrono, puoi attendere l'evento link.onload. In questo momento il | <script> all'interno dell'importazione è già stato eseguito, l'elemento personalizzato registrato e creato.

<html> 
<head> 
    <title></title> 
    <meta charset="utf-8" /> 
    <link rel="import" href="projectList.html" id="projectList" async> 
    <script> 
    projectList.onload = function() 
    { 
     console.log("import {loaded}") 
     var project_list = document.getElementsByTagName("project-list")[0] 
     project_list.custom_method("some_data") 
    } 
    </script> 
</head> 
<body> 
    <project-list id="pl"></project-list> 
    <script> 
     console.warn("custom_method is " + pl.custom_method) //undefined 
    </script> 
</body> 
</html> 

Con WebComponents.js Polyfill

In questa situazione la polyfill non un'istanza dell'oggetto creato subito dopo l'importazione viene caricato. Invece si dovrebbe ascoltare l'evento WebComponentsReady:

document.addEventListener("WebComponentsReady", function() 
{ 
    console.log("WebComponentsReady") 
    var project_list = document.getElementsByTagName("project-list")[0] 
    project_list.custom_method("some_data") 
}) 

Funziona con Firefox, IE 11, e anche con Chrome.

+0

Funzionerebbe su Chrome ma su Firefox con Polymer polyfill, non funzionerà. È sempre asincrono – user6020072

+0

Penso che questo sia collegato a questo bug: https://github.com/webcomponents/webcomponentsjs/issues/431 – user6020072

+0

Per una soluzione cross-browser ho aggiornato la mia risposta. – Supersharp

Problemi correlati