angular ng-bind-html dan direktif di dalamnya


96

Tautan Plunker

Saya memiliki elemen yang saya ingin mengikatkan html padanya.

<div ng-bind-html="details" upper></div>

Itu bekerja. Sekarang, bersamaan dengan itu saya juga memiliki arahan yang terikat pada html yang terikat:

$scope.details = 'Success! <a href="#/details/12" upper>details</a>'

Tetapi arahan upperdengan div dan anchor tidak dievaluasi. Bagaimana cara membuatnya bekerja?



@Chandermani tidak persis menggunakan direktif di dalam ng-bind-html-unsafe tetapi menggunakan filter. Tapi itu akan berhasil, saya baru saja membuat filter dan meneruskan ke direktif. Terima kasih!
— Amitava

@SamSerious, apakah Anda dapat menunjukkan bagaimana Anda melakukan apa yang Anda lakukan untuk filter?
— CMCDragonkai

solusi di atas tidak menangani banyak perubahan nilai solusi yang lebih baik stackoverflow.com/a/25516311/3343425
— fghibellini

Jawaban:


188

Saya juga menghadapi masalah ini dan setelah berjam-jam mencari di internet saya membaca komentar @ Chandermani, yang terbukti menjadi solusinya. Anda perlu memanggil arahan 'kompilasi' dengan pola ini:

HTML:

<div compile="details"></div>

JS:

.directive('compile', ['$compile', function ($compile) {
    return function(scope, element, attrs) {
        scope.$watch(
            function(scope) {
                // watch the 'compile' expression for changes
                return scope.$eval(attrs.compile);
            },
            function(value) {
                // when the 'compile' expression changes
                // assign it into the current DOM
                element.html(value);

                // compile the new DOM and link it to the current
                // scope.
                // NOTE: we only compile .childNodes so that
                // we don't get into infinite loop compiling ourselves
                $compile(element.contents())(scope);
            }
        );
    };
}])

Anda dapat melihat biola yang berfungsi di sini


1
Sejalan # 2, yaitu. function(scope, element, attrs), dari mana Anda mendapatkan tiga argumen, cakupan , elemen , dan atribut tersebut ?
— spaffy

1
@spaffy - mereka adalah bagian dari tanda tangan kerangka kerja Angular untuk linkproperti. Mereka akan diteruskan secara otomatis setiap kali linkdipanggil oleh kerangka Angular. Mereka akan selalu tersedia.
— Ben

1
Sudah selesai dilakukan dengan baik. Anda menyelamatkan saya pada jam-jam pencarian yang sama. Saya menarik konten dari REST API tampilan SharePoint, yang berisi markup Angular seperti ng-repeat. Arahan Anda membuat semuanya bekerja. Terima kasih!
— Phil Nicholas

Terima kasih atas arahan Anda, ini memperbaiki masalah yang saya alami. Sekarang kode sudut dikompilasi tetapi terlalu banyak kali. Sebuah ng-pengulangan dengan 3 objek berubah menjadi nilai yang sama hanya masing-masing 3x. Apa yang salah di sini?
— Jason

2
Jika Anda telah menggunakan $sce.trustAsHtmldari fungsi lain untuk membuat HTML yang akan "dikompilasi" dengan petunjuk ini, Anda harus menghapusnya. Terima kasih kepada @apoplexy
— Burak Tokak

36

Terima kasih atas jawaban hebat vkammerer. Satu pengoptimalan yang saya rekomendasikan adalah tidak menonton setelah kompilasi berjalan satu kali. $ Eval dalam ekspresi jam tangan dapat memiliki implikasi kinerja.

    angular.module('vkApp')
  .directive('compile', ['$compile', function ($compile) {
      return function(scope, element, attrs) {
          var ensureCompileRunsOnce = scope.$watch(
            function(scope) {
               // watch the 'compile' expression for changes
              return scope.$eval(attrs.compile);
            },
            function(value) {
              // when the 'compile' expression changes
              // assign it into the current DOM
              element.html(value);

              // compile the new DOM and link it to the current
              // scope.
              // NOTE: we only compile .childNodes so that
              // we don't get into infinite loop compiling ourselves
              $compile(element.contents())(scope);

              // Use un-watch feature to ensure compilation happens only once.
              ensureCompileRunsOnce();
            }
        );
    };
}]);

Ini biola bercabang dua dan diperbarui.


Bisakah saya meminta sebaliknya?
— Sanyam Jain

ini tidak berfungsi sebagai tanggapan dari ajax tetapi pekerjaan jawaban yang diterima
— foozhan

1
Peringatan: Biola untuk jawaban ini berfungsi, tetapi .directive()kode dalam kode yang diposting di jawaban tidak.
— Phil Nicholas

yang satu ini berhasil untuk saya. jawaban yang dipilih akan memicu "Kesalahan: $ rootScope: infdig Infinite $ digest Loop"
— Gabriel Andrei

Anda tidak perlu explict $eval- Anda bisa menggunakan attrs.compilelangsung sebagai pengganti fungsi anonim yang diawasi. Jika Anda hanya memberikan ekspresi string, angular akan tetap memanggilnya $eval.
— Dan King

28

Tambahkan direktif angular-bind-html-compile ini

.directive('bindHtmlCompile', ['$compile', function ($compile) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$watch(function () {
        return scope.$eval(attrs.bindHtmlCompile);
      }, function (value) {
        // Incase value is a TrustedValueHolderType, sometimes it
        // needs to be explicitly called into a string in order to
        // get the HTML string.
        element.html(value && value.toString());
        // If scope is provided use it, otherwise use parent scope
        var compileScope = scope;
        if (attrs.bindHtmlScope) {
          compileScope = scope.$eval(attrs.bindHtmlScope);
        }
        $compile(element.contents())(compileScope);
      });
    }
  };
}]);

Gunakan seperti ini:

<div bind-html-compile="data.content"></div>

Sangat mudah :)


1
Hati-hati, jika Anda mengirimkan sesuatu seperti ini: "$ scope.loadContent = function () {return $ sce.trustAsHtml (require ('html / main-content.html'));};" untuk itu Anda bisa mendapatkan loop intisari tak terbatas. Tanpa trustAsHtml itu bekerja.
— Lakatos Gyula

13

Sayangnya saya tidak memiliki reputasi yang cukup untuk berkomentar.

Saya tidak bisa membuat ini bekerja selama berabad-abad. Saya memodifikasi ng-bind-htmlkode saya untuk menggunakan arahan khusus ini, tetapi saya gagal menghapus $scope.html = $sce.trustAsHtml($scope.html)yang diperlukan agar ng-bind-html berfungsi. Segera setelah saya menghapus ini, fungsi kompilasi mulai bekerja.


6

Bagi siapa pun yang berurusan dengan konten yang telah dijalankan di $sce.trustAsHtmlsini, itulah yang harus saya lakukan secara berbeda

function(scope, element, attrs) {
    var ensureCompileRunsOnce = scope.$watch(function(scope) {
            return $sce.parseAsHtml(attrs.compile)(scope);
        },
        function(value) {
            // when the parsed expression changes assign it into the current DOM
            element.html(value);

            // compile the new DOM and link it to the current scope.
            $compile(element.contents())(scope);

            // Use un-watch feature to ensure compilation happens only once.
            ensureCompileRunsOnce();
        });
}

Ini hanya linkbagian dari direktif karena saya menggunakan tata letak yang berbeda. Anda juga perlu menyuntikkan $scelayanan $compile.


-2

Solusi terbaik yang saya temukan! Saya menyalinnya dan berfungsi persis seperti yang saya butuhkan. Terima kasih, terima kasih, terima kasih ...

dalam fungsi tautan direktif yang saya miliki

app.directive('element',function($compile){
  .
  .
     var addXml = function(){
     var el = $compile('<xml-definitions definitions="definitions" />')($scope);
     $scope.renderingElement = el.html();
     }
  .
  .

dan dalam template direktif:

<span compile="renderingElement"></span>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.