1

我有一個按鈕(在左側導航端),點擊哪個,我想在右側(內容部分)顯示模板(.html)。模板(.html)路徑將從Web服務中獲取,並且每次都會有所不同(因此沒有硬編碼值)。Angular 2 - bypassSecurityTrustHtml以及旁路SecuritySecurityTrustScript

該模板(.html)可以有它自己的腳本標記。 Till Angular 1.x使用ng-include標籤很容易,但似乎Angular 2不再支持它。

我用下面的解決方法能夠顯示HTML內容(以及CSS) -

this.sanitizer.bypassSecurityTrustHtml(url); 

但腳本沒有得到加載或執行。

在此先感謝您的幫助。

回答

1

當您的HTML內容中有單個腳本標記時,[innerHTML]的選項可以爲您工作。但是如果你有多個腳本標籤加載HTML內容比它不是一個可行的選擇,因爲它不能保證腳本的加載和執行順序。爲此,您必須將HTML添加到任何元素中,並逐個按順序加載腳本。

以下解決方案是正確這裏解釋 - https://ghinda.net/article/script-tags/

你的HTML應該像 -

<div id="scripts"></div> 
<div id="content"></div> 

在第一個div中,所有的腳本將獲得附加和第二,所有的HTML內容將是追加。

首先將您的HTML轉換爲字符串並將所有腳本標記推入scriptArr []。

// run the scripts inside the dom node 

    if (scriptArr.length > 0) { 
     var $container = document.getElementById('scripts') 
     $container.innerHTML = scriptArr 
     runScripts($container) 
    } 

/* helpers */ 

// runs an array of async functions in sequential order 
function seq(arr, callback, index) { 
    // first call, without an index 
    if (typeof index === 'undefined') { 
     index = 0 
    } 

    arr[index](function() { 
     index++ 
     if (index === arr.length) { 
      callback() 
     } else { 
      seq(arr, callback, index) 
     } 
    }) 
} 

// trigger DOMContentLoaded 
function scriptsDone() { 
    var DOMContentLoadedEvent = document.createEvent('Event') 
    DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true) 
    document.dispatchEvent(DOMContentLoadedEvent) 
} 

/* script runner */ 

function insertScript($script, callback) { 
    var s = document.createElement('script') 
    if (!s.type) { 
     s.type = 'text/javascript' 
    } 
    if ($script.src) { 
     s.onload = callback 
     s.onerror = callback 
     s.src = $script.src 
    } else { 
     s.textContent = $script.innerText 
    } 

    // re-insert the script tag so it executes. 
    document.head.appendChild(s) 

    // clean-up 
    $script.parentNode.removeChild($script) 

    // run the callback immediately for inline scripts 
    if (!$script.src) { 
     callback() 
    } 
} 

// https://html.spec.whatwg.org/multipage/scripting.html 
var runScriptTypes = [ 
      'application/javascript', 
      'application/ecmascript', 
      'application/x-ecmascript', 
      'application/x-javascript', 
      'text/ecmascript', 
      'text/javascript', 
      'text/javascript1.0', 
      'text/javascript1.1', 
      'text/javascript1.2', 
      'text/javascript1.3', 
      'text/javascript1.4', 
      'text/javascript1.5', 
      'text/jscript', 
      'text/livescript', 
      'text/x-ecmascript', 
      'text/x-javascript' 
     ] 

function runScripts($container) { 
    // get scripts tags from a node 
    var $scripts = $container.querySelectorAll('script') 
    var runList = [] 
    var typeAttr 

    [].forEach.call($scripts, function ($script) { 
     typeAttr = $script.getAttribute('type') 

     // only run script tags without the type attribute 
     // or with a javascript mime attribute value 
     if (!typeAttr || (runScriptTypes ? runScriptTypes.indexOf(typeAttr) !== -1 : 'text/javascript')) { 
      runList.push(function (callback) { 
       insertScript($script, callback) 
      }) 
     } 
    }) 

    // insert the script tags sequentially 
    // to preserve execution order 
    seq(runList, scriptsDone) 
} 

let fragment = document.createRange() 
    .createContextualFragment(html); 

// fragment.baseURI = 'http://toolsqaplp/publish/Dev_Testing/n1d/DS_MAC/en/CATMMGSkillets_en.edu/CATMMGEdc0020_en.doc/src/'; 
document.getElementById('content') 
    .appendChild(fragment); 
+0

感謝您的回答。 – kkok

0

official document表示bypassSecurityTrustHtml()應該適用於您的情況。

我還假設您必須使用[innerHTML]屬性來填充目標容器中的內容。

我有一種類似的需求,我需要單個腳本標記單個HTML標記。我爲此使用了bypassSecurityTrustResourceUrl()

return this.sanitizer.bypassSecurityTrustResourceUrl(url) 

我很肯定它會在你的情況下工作,因爲你正在獲取可執行文件源。

您也可以嘗試combimation bypassSecurityTrustScript()bypassSecurityTrustHtml()