เทมเพลตไดนามิกคำสั่ง Angular.jsURL


169

ฉันมีแท็กที่กำหนดเองในrouteProviderแม่แบบที่เรียกใช้directiveแม่แบบ versionแอตทริบิวต์จะมีประชากรโดยขอบเขตซึ่งจากนั้นจะเรียกร้องให้แม่แบบที่เหมาะสม

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

เพลงสวดมีหลายเวอร์ชั่นโดยยึดตามสัปดาห์และวันที่ ฉันคาดว่าจะใช้คำสั่งเพื่อเติม.htmlส่วนที่ถูกต้อง 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
    }
});

มีหลายไฟล์ในไดเรกทอรีเนื้อหาที่มีความโดดเด่นมีbefore-1-monday.html, before-2-tuesday.html...


1
ซ้ำซ้อนที่เป็นไปได้ของDynamic templateUrl - AngularJS
Nick Grealy

หากคุณกำลังใช้ AngularJS 1.5+ ให้ตรวจสอบโซลูชันที่สวยงามนี้: stackoverflow.com/a/41743424/1274852
hkong

คำตอบ:


184

คุณสามารถใช้ng-includeคำสั่ง

ลองสิ่งนี้:

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 สำหรับการดูverคุณสมบัติ

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
มันเป็นทางออกที่ดี มีวิธีเขียนหรือไม่ว่าสามารถรองรับหลายกรณีได้หรือไม่? ปัจจุบันเมื่อตั้งค่าขอบเขตแล้วจะไม่รู้จัก attrs.ver ใหม่
Alen Giliana

1
คุณหมายถึงคุณต้องการที่จะดูverการเปลี่ยนแปลงคุณลักษณะและสั่งการแสดงผล?
pgregory

1
ขอบคุณสำหรับการชี้แจง หากคุณประกาศคำสั่งวิธีการโพสต์ในอัพเดทกรณีการใช้งานของคุณเมื่อคุณใช้หลายคน<hymn ...>ควรจะทำงานได้ดี หรืออาจจะถึงเวลาที่จะสร้างต้นแบบที่jsfilddle ?
pgregory

1
สวัสดี @AlenGiliana ผมve take a look at your site, and changed [JSFiddle](http://jsfiddle.net/JQgG5/6/). All you need is ขอบเขต: {} `ในการประกาศคำสั่ง - ขอบเขตการแยก นอกจากนี้ฉันขอแนะนำให้คุณใช้เชิงมุมรุ่นสุดท้าย <script type="text/ng-template" id="...">- เป็นทางเลือกในท้องถิ่นสำหรับหน้า html
pgregory

1
คุณหมายถึงใช้ Angular 1.2.1 หรือไม่ ขอบคุณสำหรับความช่วยเหลือโดยวิธีการที่เส้นโค้งการเรียนรู้นี้เป็น :) บ้า
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'
       }
   }
});

ดังนั้นคุณสามารถให้ templateUrl ผ่านมาร์กอัป

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

ตอนนี้คุณแค่ต้องระวังว่าcontentUrlคุณสมบัติจะเติมด้วยพา ธ ที่สร้างขึ้นแบบไดนามิก


4
ดี แต่ ... ฉันสามารถเข้าถึงแอททริบิวต์ขอบเขตจากฟังก์ชัน templateUrl ได้หรือไม่ templateUrl ขึ้นอยู่กับค่าขอบเขต แต่ฉันไม่สามารถเข้าถึงได้ :(
josec89

1
ฉันดีใจที่คุณพบวิธีแก้ปัญหา ฉันจะไม่แนะนำคำสั่งที่มีการพึ่งพาพ่อแม่ของมันจนกว่าจะมีการตั้งค่าตัวควบคุมที่ต้องการส่วนหนึ่งของคำสั่ง
Andrej Kaurin

11
ที่สุด! สิ่งที่ฉันกำลังมองหา! ฉันไม่ทราบว่าฉันสามารถเข้าถึง elem และ attrs จากฟังก์ชัน templateUrl ได้ ขอขอบคุณ!
coryvb123

7
templateUrl ถูกเรียกหนึ่งครั้งต่อคำสั่งจะไม่ถูกเรียกใช้ในการเริ่มต้นอินสแตนซ์ของแต่ละคำสั่งระวัง !!! มันอาจจะเป็นข้อผิดพลาดในเชิงมุมแม้ว่า ...
Lu4

2
ฉันยังไม่ได้ตรวจสอบ once per $compile phaseแต่ยังตามผลการวิจัยล่าสุดของฉันมันอาจจะมีมูลค่าการกล่าวขวัญว่ามันเป็น กล่าวอีกนัยหนึ่งถ้าคุณใช้ng-repeatกับคำสั่งของคุณและต้องการตั้งค่าเทมเพลตแต่ละรายการตามng-repeatบริบทรายการเฉพาะมันจะไม่ทำงานเนื่องจาก$compileเฟสจะดำเนินการตามคำสั่งของคุณหนึ่งครั้งก่อนที่จะเกิดng-repeatขึ้นจริง ดังนั้นในความหมายว่ามันถูกเรียกว่าครั้ง ...
Lu4

6

ขอบคุณ @pgregory ฉันสามารถแก้ไขปัญหาของฉันโดยใช้คำสั่งนี้สำหรับการแก้ไขแบบอินไลน์

.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

คุณไม่ต้องการคำสั่งกำหนดเองที่นี่ เพียงใช้แอตทริบิวต์ng-include src มันถูกรวบรวมเพื่อให้คุณสามารถใส่รหัสภายใน ดูพลั่วเกอร์พร้อมทางออกสำหรับปัญหาของคุณ

<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

ฉันมีปัญหาเดียวกันและฉันแก้ไขในทางที่แตกต่างจากคนอื่นเล็กน้อย ฉันใช้ 1.4.4 เชิงมุม

ในกรณีของฉันฉันมีแม่แบบเชลล์ที่สร้างแผง 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>

ฉันต้องการรวมเทมเพลตบอดี้ของพาเนลขึ้นกับเส้นทาง

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

ฉันมีแม่แบบต่อไปนี้รวมอยู่เมื่อเส้นทางคือ#/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>

เทมเพลต panel-body.html ดังต่อไปนี้:

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

ข้อมูลตัวอย่างในกรณีที่มีคนต้องการไป:

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

0

ฉันมีตัวอย่างเกี่ยวกับเรื่องนี้

<!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>'
        }
    })
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.