ng-includeノードをテンプレートに置き換えますか?


85

ちょっと角度の新しい。ng-includeノードをインクルードされたテンプレートのコンテンツに置き換えることは可能ですか?たとえば、次のようになります。

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <div ng-include src="'test.html'"></div>
</div>

生成されるhtmlは次のとおりです。

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <div ng-include src="'test.html'">
        <span class="ng-scope"> </span>
        <p>Test</p>
        <span class="ng-scope"> </span>
    </div>
</div>

しかし、私が欲しいのは:

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <p>Test</p>
</div>

1
'test.html'URLではなくテンプレートを使用するために一重引用符を削除します
charlietfl 2013年

1
ng-includeのドキュメントのコメントを読むと、テンプレートの場合は一重引用符で囲まれ、URLの場合は文字列が囲まれていないようです。また、関連する
スタックオーバーフローの

あなたはドキュメントを読んでいて、後方にリンクした投稿を投稿しています
charlietfl 2013年

回答:


134

これと同じ問題が発生しましたが、ng-includeの機能に動的テンプレートを含める必要がありました。動的なBootstrapツールバーを作成していて、CSSスタイルを適切に適用するためのよりクリーンなマークアップが必要でした。

興味のある人のために私が思いついた解決策は次のとおりです。

HTML:

<div ng-include src="dynamicTemplatePath" include-replace></div>

カスタムディレクティブ:

app.directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A', /* optional */
        link: function (scope, el, attrs) {
            el.replaceWith(el.children());
        }
    };
});

上記の例でこのソリューションを使用した場合、scope.dynamicTemplatePathを「test.html」に設定すると、目的のマークアップが得られます。


Angular v1.2 +が必要
colllin 2014年


これはAngular1.2.5 +で機能します。1.2.4の場合、1つのng-includeと別のng-includeがある場合、失敗します。#5247のせいで推測していますが、よくわかりません。自分で変更ログを参照してください。ここれるPlunkrは、角度1.2.5に1.2.4(変更でこの問題を実証し、それが動作ご覧:-)!
ピーターV.Mørch

9
このようなDOM操作はかなりハッキーであることに注意してください。含まれているテンプレートのルート要素がng-repeatのようなものを使用している場合は問題があります。結果をDOMに挿入することはできません。
グリア2015

1
これに対する私の答えを参照してください。prelink関数はすでに子要素で実行されているため、これは失敗します。
サイダバック2015年

28

@ user1737909のおかげで、ng-includeが最適な方法ではないことに気づきました。指令はより良いアプローチであり、より明確です。

var App = angular.module('app', []);

App.directive('blah', function() {
    return {
        replace: true,
        restrict: 'E',  
        templateUrl: "test.html"
    };
});

HTMLの場合:

<blah></blah>

2
ありがとう!ng-includeソリューションを探していましたが、これはディレクティブの方が優れていることに気づきました
Matt Kim

replace:trueテンプレートでは非推奨としてマークされていることに注意してください。非推奨のステータスがあるため、このソリューションの使用は避けたいと思います。
ピーターV.Mørch

@PeterV.Mørchありがとう。興味のある人のために、これはコミットです:github.com/angular/angular.js/commit/…。複雑さ(およびおそらく他の理由)のために非推奨になったようです。
SunnySydeUp 2014

15

私は同じ問題を抱えていました、私のサードパーティのcssスタイルシートは余分なDOM要素を好きではありませんでした。

私の解決策は非常に単純でした。ng-include1を上に移動するだけです。だから代わりに

<md-sidenav flex class="md-whiteframe-z3" md-component-id="left" md-is-locked-open="$media('gt-md')">
  <div ng-include="myService.template"></span>
</md-sidenav>

私は単にしました:

<md-sidenav flex class="md-whiteframe-z3" md-component-id="left" md-is-locked-open="$media('gt-md')" ng-include="myService.template">
</md-sidenav>

これはほとんどの状況で機能すると思いますが、技術的には質問の内容ではありません。


10

別の方法は、独自の単純なreplace / includeディレクティブを作成することです。

    .directive('myReplace', function () {
               return {
                   replace: true,
                   restrict: 'A',
                   templateUrl: function (iElement, iAttrs) {
                       if (!iAttrs.myReplace) throw new Error("my-replace: template url must be provided");
                       return iAttrs.myReplace;
                   }
               };
           });

これは、次のように使用されます。

<div my-replace="test.html"></div>

9

これは子供を置き換える正しい方法です

angular.module('common').directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            tElement.replaceWith(tElement.children());
            return {
                post : angular.noop
            };
        }
    };
});

4
含まれている部分的なhtmlにはng-repeatがあり、これがそれらを解決する唯一の答えです!どうもありがとう。
Saad Benbouzid 2016年

私はから機能用コンテンツを移動しなければならなかったcompilelink私の要素は、コンパイル段階で空だったので、。
イタチ2017

3

次のディレクティブは、ng-includeネイティブディレクティブ機能を拡張します。

コンテンツの準備ができて読み込まれると、元の要素を置き換えるイベントリスナーが追加されます。

元の方法で使用し、「replace」属性を追加するだけです。

<ng-include src="'src.html'" replace></ng-include>

または属性表記付き:

<div ng-include="'src.html'" replace></div>

ディレクティブは次のとおりです(依存関係として「include-replace」モジュールを含めることを忘れないでください)。

angular.module('include-replace', []).directive('ngInclude', function () {
    return {
        priority: 1000,
        link: function($scope, $element, $attrs){

            if($attrs.replace !== undefined){
                var src = $scope.$eval($attrs.ngInclude || $attrs.src);

                var unbind = $scope.$on('$includeContentLoaded', function($event, loaded_src){
                    if(src === loaded_src){
                        $element.next().replaceWith($element.next().children());
                        unbind();
                    };
                });
            }
        }
    };
});

2

@BradyIsomが提供するソリューションよりも安全なソリューションを使用します。

テンプレートを削除する前に、テンプレートがロードさonloadng-includeていることを確認するために、によって指定されたオプションに依存することを好みます。

.directive('foo', [function () {
    return {
        restrict: 'E', //Or whatever you need
        scope: true,
        template: '<ng-include src="someTemplate.html" onload="replace()"></ng-include>',
        link: function (scope, elem) {
            scope.replace = function () {
                elem.replaceWith(elem.children());
            };
        }
    };
}])

すべてが最初のディレクティブ内で処理されるため、2番目のディレクティブは必要ありません。


角度1.5では、ディレクティブ要素の最初の子がコメントであることに注意してください。私はその後、NG-include要素を取得し、確認しましたので、その子に置き換える: let ngInclude = angular.element( element[ 0 ].querySelector( 'ng-include' ) ); ngInclude.replaceWith( ngInclude.children() );
Mattijs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.