Mẫu động lực chỉ thị Angular.js


169

Tôi có một thẻ tùy chỉnh trong một routeProvidermẫu mà gọi cho một directivemẫu. Các versionthuộc tính sẽ được áp dụng bởi phạm vi mà sau đó gọi cho mẫu đúng.

<hymn ver="before-{{ week }}-{{ day }}"></hymn>

Có nhiều phiên bản của bài thánh ca dựa trên tuần và ngày. Tôi đã dự đoán sẽ sử dụng chỉ thị để điền vào .htmlphần chính xác . Các biến không được đọc bởi templateUrl.

emanuel.directive('hymn', function() {
    var contentUrl;
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            // concatenating the directory to the ver attr to select the correct excerpt for the day
            contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
        },
        // passing in contentUrl variable
        templateUrl: contentUrl
    }
});

Có nhiều tập tin trong trích đoạn thư mục đó được dán nhãn before-1-monday.html, before-2-tuesday.html...


1
bản sao có thể có của mẫu
DynamicUrl

nếu bạn đang sử dụng AngularJS 1.5+, hãy kiểm tra giải pháp tao nhã này: stackoverflow.com/a/41743424/1274852
hkong

Câu trả lời:


184

Bạn có thể sử dụng ng-includechỉ thị.

Hãy thử một cái gì đó như thế này:

emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           scope.getContentUrl = function() {
                return 'content/excerpts/hymn-' + attrs.ver + '.html';
           }
       },
       template: '<div ng-include="getContentUrl()"></div>'
   }
});

CẬP NHẬT. để xem verthuộc tính

emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           scope.contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
           attrs.$observe("ver",function(v){
               scope.contentUrl = 'content/excerpts/hymn-' + v + '.html';
           });
       },
       template: '<div ng-include="contentUrl"></div>'
   }
});

1
Giải pháp tuyệt vời của nó. Có cách nào để viết nó mà nó có thể xử lý nhiều trường hợp không? Hiện tại, một khi phạm vi được đặt, nó không nhận ra attrs.ver mới.
Alen Giliana

1
Bạn có nghĩa là, bạn muốn xem verthay đổi thuộc tính và chỉ thị rerender?
tập hợp

1
Cảm ơn bạn đã làm rõ. Nếu bạn khai báo chỉ thị theo cách được đăng trong upd., Trường hợp sử dụng của bạn khi bạn sử dụng nhiều <hymn ...>sẽ hoạt động tốt. Hoặc có lẽ đã đến lúc xây dựng một nguyên mẫu tại jsfilddle ?
tập hợp

1
Xin chào @AlenGiliana, tôi ve take a look at your site, and changed [JSFiddle](http://jsfiddle.net/JQgG5/6/). All you need is phạm vi: {} `trong khai báo chỉ thị - cách ly phạm vi . Ngoài ra tôi thực sự khuyên bạn nên sử dụng phiên bản cuối cùng của góc. <script type="text/ng-template" id="...">- là thay thế cục bộ cho các trang html
tập hợp

1
Bạn có nghĩa là sử dụng Angular 1.2.1? Cảm ơn bạn đã giúp đỡ, đường cong học tập này là điên rồ :)
Alen Giliana

313
emanuel.directive('hymn', function() {
   return {
       restrict: 'E',
       link: function(scope, element, attrs) {
           // some ode
       },
       templateUrl: function(elem,attrs) {
           return attrs.templateUrl || 'some/path/default.html'
       }
   }
});

Vì vậy, bạn có thể cung cấp templateUrl thông qua đánh dấu

<hymn template-url="contentUrl"><hymn>

Bây giờ bạn chỉ cần quan tâm rằng nội dung thuộc tínhUrl cư trú với đường dẫn được tạo động.


4
Đẹp, nhưng ... tôi có thể truy cập vào các thuộc tính phạm vi từ hàm templateUrl không?
MẫuUrl

1
Tôi vui mừng bạn tìm thấy giải pháp. Tôi sẽ KHÔNG đề nghị chỉ thị có sự phụ thuộc vào cha mẹ của nó trừ khi nó là bộ điều khiển được đặt trong yêu cầu một phần của lệnh.
Andrej Kaurin

11
Cuối cùng! Chính xác những gì tôi đang tìm kiếm! Tôi đã không nhận ra rằng tôi có quyền truy cập vào elem và attrs từ một hàm templateUrl. CẢM ƠN!
coryvb123

7
templateUrl được gọi một lần cho mỗi lệnh, nó không được gọi theo từng khởi tạo thể hiện lệnh, hãy cẩn thận !!! Nó có thể là lỗi ở góc cạnh ...
Lu4 10/07/2015

2
Tôi chưa kiểm tra nó nhưng theo phát hiện mới nhất của tôi, có lẽ đáng nói là nó once per $compile phase. Nói cách khác, nếu bạn sử dụng ng-repeatvới chỉ thị của mình và muốn đặt mẫu riêng dựa trên ng-repeatbối cảnh mục cụ thể , thì nó sẽ không hoạt động, vì $compilegiai đoạn đi qua chỉ thị của bạn một lần trước khi thực tế ng-repeatxảy ra. Vì vậy, theo nghĩa đó, nó được gọi một lần ...
Lu4

6

Nhờ @pgregory, tôi có thể giải quyết vấn đề của mình bằng cách sử dụng chỉ thị này để chỉnh sửa nội tuyến

.directive("superEdit", function($compile){
    return{
        link: function(scope, element, attrs){
            var colName = attrs["superEdit"];
            alert(colName);

            scope.getContentUrl = function() {
                if (colName == 'Something') {
                    return 'app/correction/templates/lov-edit.html';
                }else {
                    return 'app/correction/templates/simple-edit.html';
                }
            }

            var template = '<div ng-include="getContentUrl()"></div>';

            var linkFn = $compile(template);
            var content = linkFn(scope);
            element.append(content);
        }
    }
})

5

Bạn không cần chỉ thị tùy chỉnh ở đây. Chỉ cần sử dụng thuộc tính ngrc bao gồm src. Nó được biên dịch để bạn có thể đặt mã bên trong. Xem plunker với giải pháp cho vấn đề của bạn.

<div ng-repeat="week in [1,2]">
  <div ng-repeat="day in ['monday', 'tuesday']">
    <ng-include src="'content/before-'+ week + '-' + day + '.html'"></ng-include>
  </div>
</div>

2

Tôi có cùng một vấn đề và tôi đã giải quyết theo một cách hơi khác so với những người khác. Tôi đang sử dụng góc 1.4.4.

Trong trường hợp của tôi, tôi có một mẫu shell tạo bảng CSS Bootstrap:

<div class="class-container panel panel-info">
    <div class="panel-heading">
        <h3 class="panel-title">{{title}} </h3>
    </div>
    <div class="panel-body">
        <sp-panel-body panelbodytpl="{{panelbodytpl}}"></sp-panel-body>
    </div>
</div>

Tôi muốn bao gồm các mẫu cơ thể bảng điều khiển tùy thuộc vào tuyến đường.

    angular.module('MyApp')
    .directive('spPanelBody', ['$compile', function($compile){
        return {
            restrict        : 'E',
            scope : true,
            link: function (scope, element, attrs) {
                scope.data = angular.fromJson(scope.data);
                element.append($compile('<ng-include src="\'' + scope.panelbodytpl + '\'"></ng-include>')(scope));
            }
        }
    }]);

Sau đó tôi có mẫu sau bao gồm khi tuyến đường là #/students:

<div class="students-wrapper">
    <div ng-controller="StudentsIndexController as studentCtrl" class="row">
        <div ng-repeat="student in studentCtrl.students" class="col-sm-6 col-md-4 col-lg-3">
            <sp-panel 
            title="{{student.firstName}} {{student.middleName}} {{student.lastName}}"
            panelbodytpl="{{'/student/panel-body.html'}}"
            data="{{student}}"
            ></sp-panel>
        </div>
    </div>
</div>

Mẫu panel-body.html như sau:

Date of Birth: {{data.dob * 1000 | date : 'dd MMM yyyy'}}

Dữ liệu mẫu trong trường hợp ai đó muốn đi:

var student = {
    'id'            : 1,
    'firstName'     : 'John',
    'middleName'    : '',
    'lastName'      : 'Smith',
    'dob'           : 1130799600,
    'current-class' : 5
}

0

Tôi có một ví dụ về điều này.

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  </head>

  <body>
    <div class="container-fluid body-content" ng-controller="formView">
        <div class="row">
            <div class="col-md-12">
                <h4>Register Form</h4>
                <form class="form-horizontal" ng-submit="" name="f" novalidate>
                    <div ng-repeat="item in elements" class="form-group">
                        <label>{{item.Label}}</label>
                        <element type="{{item.Type}}" model="item"></element>
                    </div>
                    <input ng-show="f.$valid" type="submit" id="submit" value="Submit" class="" />
                </form>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
    <script src="app.js"></script>
  </body>

</html>

angular.module('app', [])
    .controller('formView', function ($scope) {
        $scope.elements = [{
            "Id":1,
            "Type":"textbox",
            "FormId":24,
            "Label":"Name",
            "PlaceHolder":"Place Holder Text",
            "Max":20,
            "Required":false,
            "Options":null,
            "SelectedOption":null
          },
          {
            "Id":2,
            "Type":"textarea",
            "FormId":24,
            "Label":"AD2",
            "PlaceHolder":"Place Holder Text",
            "Max":20,
            "Required":true,
            "Options":null,
            "SelectedOption":null
        }];
    })
    .directive('element', function () {
        return {
            restrict: 'E',
            link: function (scope, element, attrs) {
                scope.contentUrl = attrs.type + '.html';
                attrs.$observe("ver", function (v) {
                    scope.contentUrl = v + '.html';
                });
            },
            template: '<div ng-include="contentUrl"></div>'
        }
    })
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.