A situação
Aninhada em nosso aplicativo Angular está uma diretiva chamada Page, apoiada por um controlador, que contém uma div com um atributo ng-bind-html-unsafe. Isso é atribuído a uma variável $ scope chamada 'pageContent'. Essa var recebe o HTML gerado dinamicamente a partir de um banco de dados. Quando o usuário muda para a página seguinte, é feita uma chamada ao banco de dados e a pageContent var é definida para esse novo HTML, que é renderizado na tela por meio de ng-bind-html-unsafe. Aqui está o código:
Diretiva de página
angular.module('myApp.directives')
.directive('myPage', function ($compile) {
return {
templateUrl: 'page.html',
restrict: 'E',
compile: function compile(element, attrs, transclude) {
// does nothing currently
return {
pre: function preLink(scope, element, attrs, controller) {
// does nothing currently
},
post: function postLink(scope, element, attrs, controller) {
// does nothing currently
}
}
}
};
});
Modelo da diretiva de página ("page.html" da propriedade templateUrl acima)
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
Controlador de página
angular.module('myApp')
.controller('PageCtrl', function ($scope) {
$scope.pageContent = '';
$scope.$on( "receivedPageContent", function(event, args) {
console.log( 'new page content received after DB call' );
$scope.pageContent = args.htmlStrFromDB;
});
});
Isso funciona. Vemos o HTML da página do banco de dados renderizado de maneira agradável no navegador. Quando o usuário passa para a próxima página, vemos o conteúdo da próxima página e assim por diante. Por enquanto, tudo bem.
O problema
O problema aqui é que queremos ter conteúdo interativo dentro do conteúdo de uma página. Por exemplo, o HTML pode conter uma imagem em miniatura na qual, quando o usuário clica nela, o Angular deve fazer algo impressionante, como exibir uma janela modal pop-up. Coloquei chamadas de método Angular (ng-click) nas seqüências HTML em nosso banco de dados, mas é claro que o Angular não reconhecerá chamadas ou diretivas de método, a menos que de alguma forma analise a sequência HTML, as reconheça e as compile.
No nosso banco de dados
Conteúdo da página 1:
<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>
Conteúdo da página 2:
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
De volta ao controlador de página, adicionamos a função $ scope correspondente:
Controlador de página
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
Não consigo descobrir como chamar esse método 'doSomethingAwesome' de dentro da string HTML do banco de dados. Sei que Angular precisa analisar a string HTML de alguma forma, mas como? Eu li vagos murmúrios sobre o serviço de compilação $, copiei e colei alguns exemplos, mas nada funciona. Além disso, a maioria dos exemplos mostra o conteúdo dinâmico sendo definido apenas durante a fase de vinculação da diretiva. Queremos que Page permaneça vivo durante toda a vida do aplicativo. Ele constantemente recebe, compila e exibe novo conteúdo à medida que o usuário percorre as páginas.
Em um sentido abstrato, acho que você poderia dizer que estamos tentando aninhar dinamicamente pedaços de Angular em um aplicativo Angular e precisamos ser capazes de trocá-los.
Li várias partes da documentação do Angular várias vezes, além de todos os tipos de postagens no blog, e o JS brincou com o código das pessoas. Não sei se estou entendendo completamente o Angular, ou apenas perdendo algo simples, ou talvez seja lento. De qualquer forma, eu poderia usar alguns conselhos.
Respostas:
ng-bind-html-unsafe
renderiza apenas o conteúdo como HTML. Não vincula o escopo Angular ao DOM resultante. Você precisa usar o$compile
serviço para esse fim. Eu criei esse plunker para demonstrar como usar$compile
para criar uma diretiva que processe HTML dinâmico inserido pelos usuários e vincule-o ao escopo do controlador. A fonte está publicada abaixo.demo.html
script.js
fonte
$compile(ele.contents())(scope);
- esta linha resolveu meu problema de não compilar componentes angulares que são adicionados dinamicamente. Obrigado.No angular 1.2.10, a linha
scope.$watch(attrs.dynamic, function(html) {
estava retornando um erro de caractere inválido porque estava tentando observar o valor deattrs.dynamic
qual era texto html.Corrigi isso buscando o atributo na propriedade scope
Meu exemplo
fonte
$compile(ele.contents())(scope);
- esta linha resolveu meu problema de não compilar componentes angulares que são adicionados dinamicamente. Obrigado.Encontrado em um grupo de discussão do Google. Funciona para mim.
fonte
Você pode usar
diretiva para vincular html dinamicamente. No entanto, você precisa obter os dados pelo serviço $ sce.
Por favor, veja a demonstração ao vivo em http://plnkr.co/edit/k4s3Bx
fonte
var myApp = angular.module('myApp', ['ngSanitize']);
Tente este código abaixo para vincular o html através do attr
Experimente este element.html (scope.dynamic); do que element.html (attr.dynamic);
fonte