Пример Bootstrap Accordion не работает с Angular 4 [innerHTML]

Я пытаюсь реализовать пример Bootstrap Accordion в моем приложении Angular 4.

<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
    <div class="panel-heading" role="tab" id="headingOne">
        <h4 class="panel-title">
            <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
                Collapsible Group Item #1
            </a>
        </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
        <div class="panel-body">
            Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
        </div>
    </div>
</div>
<div class="panel panel-default">
    <div class="panel-heading" role="tab" id="headingTwo">
        <h4 class="panel-title">
            <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                Collapsible Group Item #2
            </a>
        </h4>
    </div>
    <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
        <div class="panel-body">
            Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
        </div>
    </div>
</div>
<div class="panel panel-default">
    <div class="panel-heading" role="tab" id="headingThree">
        <h4 class="panel-title">
            <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
                Collapsible Group Item #3
            </a>
        </h4>
    </div>
    <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
        <div class="panel-body">
            Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
        </div>
    </div>
</div>

Это работает как очарование, когда я помещаю этот код в мой HTML-файл напрямую, но когда я пытаюсь передать этот код динамически в моем HTML-файле как [innerHTML] это не работает

Я проверил в инструментах разработчика и обнаружил, что в случае последнего тег привязки имеет только

<a class="collapsed" role="button" href="#collapseOne">

вместо

<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">

Я также думаю, что это не имеет ничего общего с ViewEncapsulation.None как я уже пробовал, и это не помогает. Я также пытался использовать @ng-bootstrap/ng-bootstrap,

Я новичок в Angular и пытаюсь понять, что мне не хватает? Любая помощь высоко ценится.

2 ответа

Решение

Когда вы вручную внедряете контент в DOM через привязки, такие как [innerHtml] или же [src] по умолчанию angular будет пытаться защитить ваших пользователей от угроз безопасности / межсайтовых скриптов

[The] DomSanitizer помогает предотвращать ошибки безопасности межсайтовых сценариев (XSS), дезинфицируя значения, чтобы их можно было безопасно использовать в различных контекстах DOM.

Например, при связывании URL-адреса в гиперссылке someValue будет очищено, так что злоумышленник не сможет внедрить, например, URL-адрес javascript: URL, который будет выполнять код на веб-сайте.

В определенных ситуациях может потребоваться отключить санацию, например, если приложению действительно необходимо создать ссылку javascript: style с динамическим значением в нем. Пользователи могут обойти защиту, создав значение с помощью одного из методов bypassSecurityTrust..., а затем связавшись с этим значением из шаблона.

https://angular.io/api/platform-browser/DomSanitizer

Жирным шрифтом в этой цитате является именно то, что нам нужно сделать здесь, чтобы достичь этого.

Вот рабочий пример использования DOMSanitizer для обхода процесса очистки для введенного html.

Суть примера здесь:

// inject the DomSanitizer
constructor(private _sanitizer: DomSanitizer){}
// bypass the sanitizer 
public get htmlProperty() : SafeHtml {
   return this._sanitizer.bypassSecurityTrustHtml(this._htmlProperty);
}

куда this._htmlProperty это огромный кусок HTML, который у вас есть в вашем вопросе в виде строки.


Примечание: это классическое замечание для людей, которые только начинают участвовать в гонке. Весь процесс дезинфекции отлично подходит для обеспечения безопасности, но это моя наименее любимая угловая функция, поскольку мне постоянно приходится это реализовывать.

Дополнительное примечание. Подумайте, следует ли разделить вашу конкретную реализацию на собственную. component на который потом можно ссылаться в форме чего-то вроде: <app-bootstrap-accordion [data]="accordionData"></app-bootstrap-accordion> где accordionData это объект, содержащий, скажем, массив данных панели, которые будут генерировать динамический аккордеон.

Ты можешь использовать [attr.data-parent]="'#bs-collapse_'+index" где индекс является переменной.

Другие вопросы по тегам