Enlaza Angularjs al elemento html creado recientemente de forma dinámica

Tengo una página de tabs con varias tabs que una vez que hace clic en llamar a un servicio para devolver algunos datos. Algunos de esos datos devuelven formularios html y son muy aleatorios. Quiero recostackr los valores que se ingresan y enviar los datos a través de un servicio al servidor. El problema que tengo es que no puedo obtener los datos de los elementos de entrada en el html que estoy creando dinámicamente.

Creé un Plunker para mostrar cuál es el problema. Tenga en cuenta que el valor de html puede cambiar en cualquier momento, por lo que el html no funcionará. Aquí está el código del plunker, pero por favor mira el plunker para ver qué está pasando.

app.js

var app = angular.module('plunker', []); app.controller('MainCtrl', function($scope, $sce, $compile) { $scope.name = 'World'; $scope.html = ""; $scope.htmlElement = function(){ var html = ""; return $sce.trustAsHtml(html); } }); 

index.html

     AngularJS Plunker document.write('');      

Hello {{name}}!

{{html}}

Una solución sería usar ngInclude con $ templateCache, como se demuestra en este Plunker .

Hay un par de cosas para notar.

La primera es que puede obtener su plantilla utilizando un servicio y agregarla a $ templateCache, como se describe aquí (ejemplo copiado):

 myApp.service('myTemplateService', ['$http', '$templateCache', function ($http, $templateCache) { $http(/* ... */).then(function (result) { $templateCache.put('my-dynamic-template', result); }); }]); 

Luego puede incluirlo en su plantilla de la siguiente manera:

 

ngInclude permitirá el enlace de datos en la cadena html, por lo que no necesita ngBindHtml.

El segundo es que, como ngInclude crea un nuevo ámbito, acceder a la propiedad html fuera del scope recién creado no funcionará correctamente a menos que acceda a él a través de un objeto en el ámbito principal (por ejemplo, ng-model="data.html" lugar de ng-model="html" . Observe que el $scope.data = {} en el ámbito primario es lo que hace que html sea accesible fuera del ámbito ngInclude en este caso.

(Consulte esta respuesta para obtener más información sobre por qué siempre debe usar un punto en su ngModels).


Editar

Como señaló, la opción ngInclude es mucho menos útil cuando se usa un servicio para devolver el HTML.

Aquí está el plunker editado con una solución basada en directivas que usa $ compile, como en el comentario anterior de David.

La adición relevante:

 app.directive('customHtml', function($compile, $http){ return { link: function(scope, element, attrs) { $http.get('template.html').then(function (result) { element.replaceWith($compile(result.data)(scope)); }); } } }) 

Basado en la respuesta de Sarah, creé una estructura para poner la directiva

 .directive('dynamic', function(AmazonService, $compile) { return { restrict: 'E', link: function(scope, element, attrs) { AmazonService.getHTML() .then(function(result){ element.replaceWith($compile(result.data)(scope)); }) .catch(function(error){ console.log(error); }); } }; }); 

Y en el html:

  

¡Gracias Sara, ayudé mucho!

Tengo una tabla dinamyc con algunas repeticiones ng, luego, cuando traté de llenar una columna con la función de callback de javascript, me dio solo en texto html como

  "span class=someclass> some_text /span>"   "span class=someclass> some_text /span>"   "span class=someclass> some_text /span>"  

Así que resolví mi problema con jquery:

 $(".tableListFilas td").each(function(){ var td_class = $(this).attr("class"); if(td_class == 'tableList_'+titulo) { **var toExtraHtml = $(this).text();** **$(this).html(toExtraHtml);** } }); 

entonces el resultado final fue bueno:

  some_text   some_text   some_text