Angular Directive Different Template

前端 未结 6 1692
渐次进展
渐次进展 2020-12-07 20:51

I have a directive myDirective with variable type. If I run I want the directive to use templateUrl: x-template.html. If I do <

相关标签:
6条回答
  • 2020-12-07 21:26

    Angular will accept a function as the template option, so you could do something like so:

    .directive('myDirective', function () {
        return {
            templateUrl: function (tElement, tAttrs) {
                if (tAttrs) {
                    if (tAttrs.type === 'X') {
                        return 'X-template.html';
                    }
                    if (tAttrs.type === 'Y') {
                        return 'Y-template.html';
                    }
                }
            }
        }
    });
    

    For more info, see the documentation for the $compile service.

    0 讨论(0)
  • 2020-12-07 21:28

    You can work around this issue using ng-include inside compile:

    app.directive('myDirective', function() {
        return {
            restrict: 'E',
            compile: function(element, attrs) {
                element.append('<div ng-include="\'' + attrs.type + '-template.html\'"></div>');
            }
        }
    });
    

    fiddle

    0 讨论(0)
  • 2020-12-07 21:32

    I solve this problem so:

    app.directive("post", function ($templateCache, $compile) {
    function getTemplate(mode) {
        switch (mode) {
            case "create":
                return "createPost.html";
            case "view":
                return "viewPost.html";
            case "delete":
                return "deletePost.html";
        }
    }
    
    var defaultMode = "view";
    
    return {
        scope: {},
        restrict: "AE",
        compile: function (elem, attrs, transclude) {
            return function ($scope, $element, $attr) {
                function updateTemplate() {
                    $element.html("");
                    $compile($templateCache.get(getTemplate($scope.mode)).trim())($scope, function (clonedElement, scope) {
                        clonedElement.appendTo($element);
    
                    });
                }
    
                $scope.mode = $attr.mode || defaultMode;
    
                $scope.$watch("mode", updateTemplate);
            }
        }
    }
    });
    

    It's probably not the best way to do this, but I have no extra scope.

    0 讨论(0)
  • 2020-12-07 21:40

    This is my version for optionally overriding a default template

    templateUrl: function (elem, attrs) {
      if (attrs.customTemplate) {
        return '/path/to/components/tmpl/' + attrs.customTemplate + '.html';
      } else {
        return '/path/to/components/tmpl/directive.html';
      }
    }
    

    e.g on a directive

    <div my-directive custom-template="custom"></div>
    
    0 讨论(0)
  • 2020-12-07 21:43

    Ok, this might help someone here :-)

    To inject your custom attr into your link or controller function use the following.

    I'm at work right now but will post a fiddle later if I get a chance :-)

    .directive('yourDirective', function() {
      return {
        restrict: 'EA',
        template: '<div></div>', // or use templateUrl with/without function
        scope: {
          myAttibute: '@myAttr' // adds myAttribute to the scope
        },
        link: function(scope) {
          console.log(scope.myAttibute);
        }
      }
    }
    

    // HTML ""

    // Console will output "foo"

    0 讨论(0)
  • 2020-12-07 21:45

    If you're willing to live on the bleeding edge with a build on the 1.1.x code path (note the warning attached to every 1.1.x build notes entry so I don't dilute this answer by repeating it again here), you're in luck--this very feature was just added in the 1.1.4 release on April 3rd. You can find the release notes for 1.1.4 here and the feature's task log includes a Jasmine test that demonstrates how to use the new functionality.

    If you're more conservative and are using a 1.0.x release, then you won't be able to accomplish this as easily, but it can be done. Mark Rajcok's solution looks like it would fit your requirements as-stated, but I would just add a few additional notes:

    • Aside from its 1.1.4 release, compile-time directives don't support modification at runtime.
      • As of 1.1.4, you can safely modify the attributes of compile-time directives, but only from another compile-time directive.
    • You may want to consider replaceWith() instead of append() since <my-directive> is not a standard-defined HTML element type.
    • If your X and Y templates contain additional directives, I don't think you'll be able to pass attributes on <my-template> through to the root element of your template so easily.
      • A directive with replace: true will transfer attributes from the source element to its replacement root, but I do not think that ngInclude will do the same from is host to the root of the included template.
      • I also seem to recall that ngInclude does not require that its template have exactly one root element.
      • You could perhaps preserve attributes on a replacement parent by using replaceWith() instead of append() and wrapping the <div ng-include=""> tag within a <div></div>. The outer <div> could hold attributes and would still be accessible after the <div ngInclude> element replaced itself with loaded content.
    • Be aware that ngInclude creates a new scope. This subjects you to a flashing yellow klaxons warning about the dangers of primitive scope models. For more information, see this fine page from Angular's GitHub depot.

    I can propose another alternative for those on 1.0.x, but it involves a fair amount of code. It's a more heavy-weight operation, but it has the upside of not only being able of switching between templates, but full-fledged directives as well. Furthermore, its behavior is more readily dynamic.

    app.directive('myDirective', function() {
        return {
            restrict: 'E',
            replace: true,
            templateUrl: 'partials/directive/my-directive.html',
            link: function(scope, element, attrs, ctrl) {
                // You can do this with isolated scope as well of course.
                scope.type = attrs.type;
            }
        }
    );
    

    my-directive.js

    <div ng-switch on="{{type}}">
        <div ng-switch-where="X" ng-include="X-template.html"></div>
        <div ng-switch-where="Y" ng-include="Y-template.html"></div>
    </div>
    

    my-directive.html

    0 讨论(0)
提交回复
热议问题