动态地将Angularjs绑定到新创建的html元素

时间:2022-10-22 07:53:35

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>