angularjs - examples - ng-model
Enlazar Angularjs al elemento HTML recién creado dinámicamente (3)
Tengo una página de pestañas con varias pestañas que una vez que se hizo clic en llamar a un servicio para devolver algunos datos. Algunos de esos datos devuelven formularios html y son muy aleatorios. Quiero recopilar 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.
He creado un Plunker para mostrar cuál es el problema. Tenga en cuenta que el valor html puede cambiar en cualquier momento, por lo que la codificación no funcionará. Aquí está el código del plunker, pero mire al plunker para ver mejor 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 = "<input type=''text'' ng-model=''html''></input>";
return $sce.trustAsHtml(html);
}
});
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write(''<base href="'' + document.location + ''" />'');</script>
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div ng-bind-html="htmlElement()"></div>
{{html}}
</body>
</html>
Basándome 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:
<dynamic></dynamic>
Gracias Sarah, ayudó mucho !!!
Tengo una tabla dinámica con algunas repeticiones ng, luego, cuando intenté rellenar una columna con la función de devolución de llamada javascript, me la proporcioné solo en texto html como
<td class="tableList_"+myValue> "span class=someclass> some_text /span>" </td>
<td class="tableList_"+myValue> "span class=someclass> some_text /span>" </td>
<td class="tableList_"+myValue> "span class=someclass> some_text /span>" </td>
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 la salida final fue buena:
<td class="tableList_COLORS"> <span class=someclass>some_text</span> </td>
<td class="tableList_COLORS"> <span class=someclass>some_text</span> </td>
<td class="tableList_COLORS"> <span class=someclass>some_text</span> </td>
Una solución sería usar ngInclude con $ templateCache, como se muestra en este Plunker .
Hay un par de cosas a tener en cuenta.
La primera es que puede obtener su plantilla usando un servicio y agregarla a $ templateCache, como se describe here (ejemplo copiado):
myApp.service(''myTemplateService'', [''$http'', ''$templateCache'', function ($http, $templateCache) {
$http(/* ... */).then(function (result) {
$templateCache.put(''my-dynamic-template'', result);
});
}]);
Luego puedes incluirlo en tu plantilla de la siguiente manera:
<div ng-include="''my-dynamic-template''"></div>
ngInclude permitirá el enlace de datos en la cadena html, por lo que no necesita ngBindHtml.
La segunda es que, dado que ngInclude crea un nuevo ámbito, acceder a la propiedad html
fuera del ámbito recién creado no funcionará correctamente a menos que acceda a él a través de un objeto en el ámbito primario (por ejemplo, ng-model="data.html"
of ng-model="html"
. Observe que $scope.data = {}
en el ámbito principal es lo que hace que el 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 sus ngModels).
Editar
Como señalaste, la opción ngInclude es mucho menos útil cuando usas 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 de David anterior.
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));
});
}
}
})