Angular.js directive dynamic templateURL

169

Saya memiliki tag khusus dalam routeProvidertemplat yang meminta directivetemplat. The versionatribut akan diisi oleh ruang lingkup yang kemudian memanggil untuk template yang tepat.

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

Ada beberapa versi nyanyian pujian berdasarkan pada minggu dan hari apa itu. Saya mengantisipasi untuk menggunakan arahan untuk mengisi bagian yang benar .html. Variabel tidak sedang dibaca oleh 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
    }
});

Ada beberapa file dalam direktori kutipan yang diberi label before-1-monday.html, before-2-tuesday.html...

Alen Giliana
sumber
1
kemungkinan duplikat Dynamic templateUrl - AngularJS
Nick Grealy
jika Anda menggunakan AngularJS 1.5+, periksa solusi elegan ini: stackoverflow.com/a/41743424/1274852
hkong

Jawaban:

184

Anda bisa menggunakan ng-includearahan.

Coba sesuatu seperti ini:

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

UPD. untuk menonton veratribut

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>'
   }
});
pgregory
sumber
1
Solusi hebatnya. Apakah ada cara untuk menulisnya sehingga dapat menangani banyak contoh? Saat ini, setelah ruang lingkup ditetapkan, ia tidak mengenali attrs.ver baru.
Alen Giliana
1
Maksud Anda, Anda ingin menonton verperubahan atribut dan direktif rerender?
pgregory
1
Terima kasih telah mengklarifikasi. Jika Anda mendeklarasikan arahan cara diposting dalam pembaruan, kasus penggunaan Anda ketika Anda menggunakan banyak <hymn ...>harus bekerja dengan baik. Atau mungkin saatnya untuk membangun prototipe di jsfilddle ?
pgregory
1
Halo @AlenGiliana, ve take a look at your site, and changed [JSFiddle](http://jsfiddle.net/JQgG5/6/). All you need is lingkup saya : {} `dalam deklarasi direktif - isolasi lingkup . Saya juga sangat menyarankan Anda untuk menggunakan versi sudut terakhir. <script type="text/ng-template" id="...">- adalah alternatif lokal untuk halaman html
pgregory
1
Apakah Anda bermaksud menggunakan Angular 1.2.1?
Omong
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'
       }
   }
});

Jadi, Anda dapat menyediakan templateUrl melalui markup

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

Sekarang Anda hanya mengurus yang properti contentUrl populates dengan jalur yang dihasilkan secara dinamis.

Andrej Kaurin
sumber
4
Bagus, tapi ... bisakah saya mengakses atribut lingkup dari fungsi templateUrl? TemplateUrl tergantung pada nilai lingkup, tetapi saya tidak dapat mengaksesnya :(
josec89
1
Saya senang Anda menemukan solusi. Saya TIDAK akan merekomendasikan direktif memiliki ketergantungan pada orang tuanya kecuali jika diatur di bagian membutuhkan direktif.
Andrej Kaurin
11
Akhirnya! Persis apa yang saya cari! Saya tidak menyadari bahwa saya memiliki akses ke elem dan attrs dari fungsi templateUrl. TERIMA KASIH!
coryvb123
7
templateUrl dipanggil sekali per direktif, itu tidak dipanggil pada setiap inisialisasi instance direktif, hati-hati !!! Mungkin ada bug di sudut ...
Lu4
2
Saya belum memeriksanya, tetapi menurut temuan terakhir saya, mungkin perlu disebutkan bahwa itu once per $compile phase. Dengan kata lain jika Anda menggunakan ng-repeatdengan arahan Anda dan ingin menetapkan template individual berdasarkan ng-repeatkonteks item tertentu , itu tidak akan berhasil, karena $compilefase berjalan melalui arahan Anda sekali sebelum ng-repeatterjadi. Jadi dalam arti itu dipanggil sekali ...
Lu4
6

Berkat @pgregory, saya bisa menyelesaikan masalah saya menggunakan arahan ini untuk mengedit inline

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

Anda tidak perlu arahan khusus di sini. Cukup gunakan atribut ng-include src. Ini dikompilasi sehingga Anda dapat memasukkan kode ke dalamnya. Lihat plunker dengan solusi untuk masalah Anda.

<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>
icem
sumber
2

Saya memiliki masalah yang sama dan saya menyelesaikannya dengan cara yang sedikit berbeda dari yang lain. Saya menggunakan sudut 1.4.4.

Dalam kasus saya, saya memiliki template shell yang membuat panel 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>

Saya ingin menyertakan templat bodi panel tergantung pada rute.

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

Saya kemudian memasukkan templat berikut saat rute #/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>

Templat panel-body.html sebagai berikut:

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

Sampel data jika seseorang ingin melakukan sesuatu:

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

Saya punya contoh tentang ini.

<!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>'
        }
    })
ddagsan
sumber