web-dev-qa-db-ja.com

Angularjsを新しく作成されたhtml要素に動的にバインドします

複数のタブがあるタブページがあり、クリックするとサービスが呼び出されてデータが返されます。そのデータの一部はhtmlフォームを返し、非常にランダムです。入力された値を収集し、サービスを介してサーバーにデータを送信します。私が抱えている問題は、動的に作成しているhtmlの入力要素からデータを取得できないことです。

Plunker を作成して、問題の内容を示しました。 html値はいつでも変更できるため、htmlのハードコーディングは機能しません。ここではプランカーからのコードですが、何が起こっているのかを最もよく把握するためにプランカーをご覧ください。

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>
18
Ty Danielson

この Plunker で示されているように、1つの解決策は$ templateCacheでngIncludeを使用することです。

注意すべき点がいくつかあります。

1つ目は、サービスを使用してテンプレートを取得し、それを$ templateCacheに追加できることです。これについては、 here (コピー例)をご覧ください。

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

次に、次のようにテンプレートに含めることができます。

<div ng-include="'my-dynamic-template'"></div>

ngIncludeはhtml文字列のデータバインディングを許可するため、ngBindHtmlは必要ありません。

2つ目は、ngIncludeが新しいスコープを作成するため、親スコープのオブジェクト(例:代わりにng-model="data.html")を介してアクセスしない限り、新しく作成されたスコープ外のhtmlプロパティへのアクセスは正しく機能しませんof ng-model="html"。この場合、親スコープの$scope.data = {}がngIncludeスコープ外でhtmlにアクセスできることに注意してください。

(ngModelで常にドットを使用する必要がある理由の詳細については、 この回答 を参照してください。)


編集

指摘したように、サービスを使用してHTMLを返す場合、ngIncludeオプションはあまり有用ではありません。

編集した plunker は、上記のDavidのコメントのように、$ compileを使用するディレクティブベースのソリューションです。

関連する追加:

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));
      });
    }
  }
})
26
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);
     });
   }
 };
});

そしてhtmlで:

<dynamic></dynamic>

サラに感謝、たくさん助けて!

6
victorkurauchi

Ng-repeatのあるdinamycテーブルがあり、1つの列を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>

そこで、jqueryの問題を解決しました。

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

最終的な出力は良好でした:

<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>  
0
Israel Vázquez