Thay thế nút ng-include bằng mẫu?


85

Kinda mới góc cạnh. Có thể thay thế nút ng-include bằng nội dung của mẫu được bao gồm không? Ví dụ, với:

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

Html được tạo là:

<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>

Nhưng điều tôi muốn là:

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

1
xóa các dấu ngoặc kép 'test.html'để sử dụng mẫu thay vì url
charlietfl

1
đọc các nhận xét của tài liệu cho ng-include, có vẻ như nó bao quanh chuỗi với các dấu ngoặc kép cho mẫu và không có url. Ngoài ra, liên quan đến câu hỏi stackoverflow
SunnySydeUp

bạn đang đọc tài liệu và đăng bài mà bạn liên kết ngược lại
charlietfl

Câu trả lời:


134

Tôi cũng gặp phải vấn đề này và vẫn muốn các tính năng của ng-include bao gồm một mẫu động. Tôi đang xây dựng một thanh công cụ Bootstrap động và tôi cần đánh dấu rõ ràng hơn để các kiểu CSS được áp dụng đúng cách.

Đây là giải pháp mà tôi đã đưa ra cho những ai quan tâm:

HTML:

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

Chỉ thị tùy chỉnh:

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

Nếu giải pháp này được sử dụng trong ví dụ trên, việc đặt scope.dynamicTemplatePath thành 'test.html' sẽ dẫn đến đánh dấu mong muốn.


Đòi hỏi góc v1.2 +
colllin

Tôi đã tham khảo câu trả lời này trong một câu hỏi tương tự: anglejs - Tránh sử dụng thêm các nút DOM khi sử dụng nginclude - Stack Overflow
Peter V. Mørch.

Điều này hoạt động cho góc 1.2.5+. Đối với 1.2.4, nếu bạn có một ng-include mà ng-include khác, nó không thành công. Tôi đoán vì # 5247 , nhưng tôi không chắc. Hãy xem Changelog cho chính bạn. Đây là một Plunkr giải thích vấn đề này với 1.2.4 (thay đổi thành 1.2.5 góc và xem nó hoạt động! :-)
Peter V. Mørch.

9
Hãy lưu ý rằng thao tác DOM như vậy khá khó khăn. Sẽ có vấn đề nếu phần tử gốc của mẫu bao gồm sử dụng một cái gì đó như ng-repeat. Nó sẽ không thể chèn kết quả trong DOM.
Guria

1
Vui lòng xem câu trả lời của tôi cho điều này, điều này sẽ không thành công vì chức năng liên kết trước sẽ đã chạy trong các phần tử con.
Sai Dubbaka

28

Vì vậy, nhờ có @ user1737909, tôi đã nhận ra rằng ng-include không phải là cách để đi. Chỉ thị là cách tiếp cận tốt hơn và rõ ràng hơn.

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

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

Trong html:

<blah></blah>

2
cảm ơn! đang tìm kiếm một giải pháp ng-bao gồm nhưng điều này đã giúp tôi nhận ra chỉ thị là tốt hơn
Matt Kim

Hãy nhớ rằng replace:truetrong các mẫu được đánh dấukhông dùng nữa . Tôi tránh sử dụng giải pháp này do tình trạng không dùng nữa.
Peter V. Mørch

@ PeterV.Mørch Cảm ơn. Đối với những người quan tâm, đây là cam kết: github.com/angular/angular.js/commit/… . Có vẻ như nó đã không được dùng nữa vì nó phức tạp (và có lẽ là những lý do khác).
SunnySydeUp

15

Tôi đã gặp vấn đề tương tự, biểu định kiểu css bên thứ 3 của tôi không thích phần tử DOM bổ sung.

Giải pháp của tôi cực kỳ đơn giản. Chỉ cần di chuyển ng-include 1 lên. Vì vậy, thay vì

<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>

Tôi chỉ đơn giản làm:

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

Tôi cá rằng điều này sẽ hoạt động trong hầu hết các tình huống, ngay cả khi về mặt kỹ thuật, nó không phải là những gì câu hỏi đang đặt ra.


10

Một cách khác là viết chỉ thị thay thế / bao gồm đơn giản của riêng bạn, ví dụ:

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

Điều này sau đó sẽ được sử dụng như sau:

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

9

Đây là cách thay con đúng

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 một phần bao gồm của tôi có một số ng-repeat, và đây là câu trả lời duy nhất giải quyết chúng! Cảm ơn rất nhiều.
Saad Benbouzid

Tôi phải chuyển nội dung hàm từ compilesang link, vì phần tử của tôi trống trong giai đoạn biên dịch.
itachi

3

Chỉ thị sau mở rộng chức năng chỉ thị riêng của ng-include.

Nó thêm một trình lắng nghe sự kiện để thay thế phần tử gốc khi nội dung đã sẵn sàng và được tải.

Sử dụng nó theo cách ban đầu, chỉ cần thêm thuộc tính "Replace":

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

hoặc với ký hiệu thuộc tính:

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

Đây là chỉ thị (hãy nhớ bao gồm mô-đun 'include-Replace' làm phụ thuộc):

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

Tôi sẽ sử dụng một giải pháp an toàn hơn giải pháp được cung cấp bởi @Brady Isom.

Tôi thích dựa vào onloadtùy chọn được cung cấp bởi ng-includeđể đảm bảo rằng mẫu được tải trước khi cố gắng xóa nó.

.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());
            };
        }
    };
}])

Không cần chỉ thị thứ hai vì mọi thứ được xử lý trong chỉ thị đầu tiên.


lưu ý rằng với góc 1,5, con đầu tiên trong phần tử chỉ thị là một nhận xét. Vì vậy, tôi đã đảm bảo rằng tôi nhận được yếu tố ng-bao gồm và sau đó thay thế nó với con của nó: let ngInclude = angular.element( element[ 0 ].querySelector( 'ng-include' ) ); ngInclude.replaceWith( ngInclude.children() );
Mattijs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.