Angular.js 지시문 동적 templateURL


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



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
설명해 주셔서 감사합니다. upd.에 게시 된 방식을 지시문으로 선언하면 여러 개를 사용할 때 유스 케이스가 <hymn ...>잘 작동합니다. 아니면 jsfilddle 에서 프로토 타입을 만들 때가 되었을까요 ?
pgregory

1
안녕하세요 @AlenGiliana, ve take a look at your site, and changed [JSFiddle](http://jsfiddle.net/JQgG5/6/). All you need is 지시문 선언 범위 격리 에서 scope : {}`입니다 . 또한 마지막 버전의 각도를 사용하는 것이 좋습니다. <script type="text/ng-template" id="...">-html 페이지의 대체 대안
pgregory

1
Angular 1.2.1을 사용 하시겠습니까? 그런데 도움을 주셔서 감사합니다,이 학습 곡선은 미친 :)입니다
알렌 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
드디어! 정확히 내가 찾던 것! templateUrl 함수에서 elem 및 attrs에 액세스 할 수 있다는 것을 몰랐습니다. 감사!
coryvb123

7
templateUrl은 지시문 당 한 번 호출되며 각 지시문 인스턴스 초기화시 호출되지 않습니다. 조심하십시오! 그것은 각도에 버그가있을 수 있습니다 ...
Lu4

2
아직 확인하지는 않았지만 최근 발견 한 바에 따르면 once per $compile phase. 즉, ng-repeat지시문과 함께 사용 하고 특정 ng-repeat항목 컨텍스트를 기반으로 개별 템플릿을 설정하려는 경우 $compile실제로 ng-repeat발생 하기 전에 단계가 지시문을 한 번 수행하기 때문에 작동하지 않습니다 . 따라서 그 의미에서 한 번
불려지고 있습니다

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.