How to specify model to a ngInclude directive in AngularJS?

前端 未结 6 1682
北海茫月
北海茫月 2020-11-30 02:48

I would like to use the same HTML template in 3 places, just each time with a different model. I know I can access the variables from the template, but there names will be d

相关标签:
6条回答
  • 2020-11-30 03:25

    I hear you! ng-include is not that reusable because it has access to the global scope. It's a little weird.

    There should be a way to set local variables. Using a new directive instead of ng-include is a cleaner solution.

    The ideal usage looks like:

    <div ng-include-template="'Partials/SummaryDetails.html'" ng-include-variables="{ 'detailsObject': language }"></div>
    

    The directive is:

    .directive(
      'ngIncludeTemplate'
      () ->
        {
          templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
          restrict: 'A'
          scope: {
            'ngIncludeVariables': '&'
          }
          link: (scope, elem, attrs) ->
            vars = scope.ngIncludeVariables()
            for key, value of vars
              scope[key] = value
        }
    )
    

    You can see that the directive doesn't use the global scope. Instead, it reads the object from ng-include-variables and add those members to its own local scope.

    It's clean and generic.

    0 讨论(0)
  • 2020-11-30 03:30
    <div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>
    
    directive('newScope', function () {
        return {
            scope: true,
            priority: 450,
            compile: function () {
                return {
                    pre: function (scope, element, attrs) {
                        scope.$eval(attrs.newScope);
                    }
                };
            }
        };
    });
    

    This is a directive that combines new-scope from John Culviner's answer with code from Angular's ng-init.

    For completeness, this is the Angular 1.2 26 ng-init source, you can see the only change in the new-scope directive is the addition of scope: true

    {
      priority: 450,
      compile: function() {
        return {
          pre: function(scope, element, attrs) {
            scope.$eval(attrs.ngInit);
          }
        };
      }
    }
    
    0 讨论(0)
  • 2020-11-30 03:40

    Quick'n'dirty solution:

    <div ng-init="details=document||language||projectSummary.ProjectResults">
    
    0 讨论(0)
  • 2020-11-30 03:41

    NOTE: this is not my original answer but this is how I'd do this after using angular for a bit.

    I would create a directive with the html template as the markup passing in the dynamic data to the directive as seen in this fiddle.

    Steps/notes for this example:

    1. Define a directive with markup in the templateUrl and attribute(s) used to pass data into the directive (named type in this example).
    2. Use the directive data in the template (named type in this example).
    3. When using the directive in the markup make sure you pass in the data from the controller scope to the directive (<address-form type="billing"></address-form> (where billing is accessing an object on the controller scope).
    4. Note that when defining a directive the name is camel cased but when used in the markup it is lower case dash delimited (ie it's named addressForm in the js but address-form in the html). More info on this can be found in the angular docs here.

    Here is the js:

    var myApp = angular.module('myApp',[]);
    
    angular.module('myApp').directive('addressForm', function() {
        return {
            restrict: 'E',
            templateUrl: 'partials/addressform.html', // markup for template
            scope: {
                type: '=' // allows data to be passed into directive from controller scope
            }
        };
    });
    
    angular.module('myApp').controller('MyCtrl', function($scope) {
        // sample objects in the controller scope that gets passed to the directive
        $scope.billing = { type: 'billing type', value: 'abc' };
        $scope.delivery = { type: 'delivery type', value: 'def' };
    });
    

    With markup:

    <div ng-controller="MyCtrl">
        <address-form type="billing"></address-form>
        <address-form type="delivery"></address-form>
    </div>
    

    ORIGINAL ANSWER (which is completely different than using a directive BTW).

    Note: The fiddle from my original answer below doesn't appear to work anymore due to an error (but keeping it here in case it is still useful)

    There was a discussion about this on the Google Group you can see it here.

    It looks like this functionality is not supported out of the box but you can use Brice's patch as described in this post.

    Here is the sample code from his jsfiddle:

    <script id="partials/addressform.html" type="text/ng-template">
        partial of type {{type}}<br>
    </script>
    
    <div ng-controller="MyCtrl">
      <ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
      <ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
    </div>
    
    0 讨论(0)
  • 2020-11-30 03:44

    There is a pull to fix this but it looks like it's dead: https://github.com/angular/angular.js/pull/1227

    Without modifying the Angular source code this will solve the problem in a reusable not-too-hacky-feeling way:

    directive('newScope', function() {
        return {
            scope: true,
            priority: 450,
        };
    });
    

    And an example:

    <div new-scope ng-init="myVar = 'one instance'" ng-include="'template.html'"></div>
    <div new-scope ng-init="myVar = 'another instance'" ng-include="'template.html'"></div>
    

    Here is a Plunker of it in action: http://plnkr.co/edit/El8bIm8ta97MNRglfl3n

    0 讨论(0)
  • 2020-11-30 03:48

    There is a rather simple solution, although I must admit, it's not what Misko would recommend. But if creating a directive is an overkill for you and getting Brice's patch is not feasible then the following will help you.

    <div ng-repeat="name in ['A']" ng-include="'partial.html'"></div>
    <div ng-repeat="name in ['B']" ng-include="'partial.html'"></div>
    
    <script type="text/ng-template" id="partial.html">
       <div>{{ name }}</div>
    </script>
    

    It's quite evident why it works. See an example here: http://jsfiddle.net/Cndc6/4/

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