I have a tab page with multiple tabs that once clicked on call a service to return some data. Some of that data returns html forms and are very random. I want to collect those values that are entered and send the data via a service back to the server. The problem I have is that I can't get the data from the input elements in the html I'm creating dynamically.
我有一个带有多个标签的标签页,一旦点击就会调用服务来返回一些数据。一些数据返回html表单,并且非常随机。我想收集输入的值并通过服务将数据发送回服务器。我遇到的问题是我无法从动态创建的html中的输入元素中获取数据。
I've created a Plunker to show what the issue is. Note that the html value can change at any time so hard-coding the html won't work. Here the code from the plunker, but please look at the plunker for the best view of whats going on.
我创建了一个Plunker来展示问题所在。请注意,html值可以随时更改,因此硬编码html将无法正常工作。这里是来自plunker的代码,但请查看plunker以了解最新情况。
app.js
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
的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>
3 个解决方案
#1
26
One solution would be to use ngInclude with $templateCache, as demonstrated in this Plunker.
一种解决方案是使用带有$ templateCache的ngInclude,如此Plunker中所示。
There are a couple things to note.
有几点需要注意。
The first is that you can fetch your template using a service and add it to the $templateCache, as described here (example copied):
首先,您可以使用服务获取模板并将其添加到$ templateCache,如此处所述(复制示例):
myApp.service('myTemplateService', ['$http', '$templateCache', function ($http, $templateCache) {
$http(/* ... */).then(function (result) {
$templateCache.put('my-dynamic-template', result);
});
}]);
Then you can include it in your template as follows:
然后,您可以将其包含在模板中,如下所示:
<div ng-include="'my-dynamic-template'"></div>
ngInclude will allow databinding on the html string, so you don't need ngBindHtml.
ngInclude将允许对html字符串进行数据绑定,因此您不需要ngBindHtml。
The second is that, as ngInclude creates a new scope, accessing the html
property outside of the newly created scope won't work properly unless you access it via an object on the parent scope (e.g. ng-model="data.html"
instead of ng-model="html"
. Notice that the $scope.data = {}
in the parent scope is what makes the html accessible outside of the ngInclude scope in this case.
第二个是,当ngInclude创建一个新范围时,访问新创建范围之外的html属性将无法正常工作,除非您通过父范围内的对象访问它(例如ng-model =“data.html”而不是ng-model =“html”。请注意,在这种情况下,父作用域中的$ scope.data = {}是使得html可以在ngInclude作用域之外访问的原因。
(See this answer for more on why you should always use a dot in your ngModels.)
(有关为什么要始终在ngModel中使用点的原因,请参阅此答案。)
Edit
编辑
As you pointed out, the ngInclude option is much less useful when using a service to return the HTML.
正如您所指出的,使用服务返回HTML时,ngInclude选项的用处不大。
Here's the edited plunker with a directive-based solution that uses $compile, as in David's comment above.
这是编辑的plunker,它带有一个使用$ compile的基于指令的解决方案,如上面David的评论。
The relevant addition:
相关补充:
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));
});
}
}
})
#2
6
Based on Sarah's answer, i created a structure to put the directive
根据Sarah的回答,我创建了一个结构来放置指令
.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);
});
}
};
});
And in the html:
并在HTML中:
<dynamic></dynamic>
Thanks Sarah, helped a lot!!!
谢谢莎拉,帮了很多!!!
#3
0
I have a dinamyc table with some ng-repeat's, then when I tried to fill one column with javascript callback function, it give me just in html text like
我有一个带有一些ng-repeat的dinamyc表,然后当我尝试使用javascript回调函数填充一列时,它只给我一些html文本
<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>
So I resolved my problem with jquery:
所以我用jquery解决了我的问题:
$(".tableListFilas td").each(function(){
var td_class = $(this).attr("class");
if(td_class == 'tableList_'+titulo)
{
**var toExtraHtml = $(this).text();**
**$(this).html(toExtraHtml);**
}
});
then the final output was good:
然后最终的输出很好:
<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>
#1
26
One solution would be to use ngInclude with $templateCache, as demonstrated in this Plunker.
一种解决方案是使用带有$ templateCache的ngInclude,如此Plunker中所示。
There are a couple things to note.
有几点需要注意。
The first is that you can fetch your template using a service and add it to the $templateCache, as described here (example copied):
首先,您可以使用服务获取模板并将其添加到$ templateCache,如此处所述(复制示例):
myApp.service('myTemplateService', ['$http', '$templateCache', function ($http, $templateCache) {
$http(/* ... */).then(function (result) {
$templateCache.put('my-dynamic-template', result);
});
}]);
Then you can include it in your template as follows:
然后,您可以将其包含在模板中,如下所示:
<div ng-include="'my-dynamic-template'"></div>
ngInclude will allow databinding on the html string, so you don't need ngBindHtml.
ngInclude将允许对html字符串进行数据绑定,因此您不需要ngBindHtml。
The second is that, as ngInclude creates a new scope, accessing the html
property outside of the newly created scope won't work properly unless you access it via an object on the parent scope (e.g. ng-model="data.html"
instead of ng-model="html"
. Notice that the $scope.data = {}
in the parent scope is what makes the html accessible outside of the ngInclude scope in this case.
第二个是,当ngInclude创建一个新范围时,访问新创建范围之外的html属性将无法正常工作,除非您通过父范围内的对象访问它(例如ng-model =“data.html”而不是ng-model =“html”。请注意,在这种情况下,父作用域中的$ scope.data = {}是使得html可以在ngInclude作用域之外访问的原因。
(See this answer for more on why you should always use a dot in your ngModels.)
(有关为什么要始终在ngModel中使用点的原因,请参阅此答案。)
Edit
编辑
As you pointed out, the ngInclude option is much less useful when using a service to return the HTML.
正如您所指出的,使用服务返回HTML时,ngInclude选项的用处不大。
Here's the edited plunker with a directive-based solution that uses $compile, as in David's comment above.
这是编辑的plunker,它带有一个使用$ compile的基于指令的解决方案,如上面David的评论。
The relevant addition:
相关补充:
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));
});
}
}
})
#2
6
Based on Sarah's answer, i created a structure to put the directive
根据Sarah的回答,我创建了一个结构来放置指令
.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);
});
}
};
});
And in the html:
并在HTML中:
<dynamic></dynamic>
Thanks Sarah, helped a lot!!!
谢谢莎拉,帮了很多!!!
#3
0
I have a dinamyc table with some ng-repeat's, then when I tried to fill one column with javascript callback function, it give me just in html text like
我有一个带有一些ng-repeat的dinamyc表,然后当我尝试使用javascript回调函数填充一列时,它只给我一些html文本
<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>
So I resolved my problem with jquery:
所以我用jquery解决了我的问题:
$(".tableListFilas td").each(function(){
var td_class = $(this).attr("class");
if(td_class == 'tableList_'+titulo)
{
**var toExtraHtml = $(this).text();**
**$(this).html(toExtraHtml);**
}
});
then the final output was good:
然后最终的输出很好:
<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>