使指令使用父范围?

时间:2014-01-09 05:14:51

标签: angularjs

我做了一个像这样的include指令:

Log.directive 'logList', () ->
    return {
        restrict: 'E'
        scope:
            type: '='
        templateUrl: "/partials/log"
    }

我在页面上包含了两次,并且希望两者都使用它们所包含的根范围。自从将这个重复的HTML放入include之后,我就不得不像$ parent那样搞乱了。$ parent.something。

3 个答案:

答案 0 :(得分:1)

只要您在指令声明范围字段中指定任何内容,AngularJS就会创建隔离范围。顾名思义,此隔离范围不会从父范围继承,因此无法直接访问父范围值。

但是,根据具体情况,有多种方法可以访问父作用域属性,而不使用容易出错的 $ parent

Plunker Demo

例如,通过观察属性selfelf的值,我们不需要创建一个独立的范围,因此我们可以访问所有容器范围属性:

myApp.controller('MyController', function($scope) {
  $scope.demo = { myValue: "Shared scope value" };
});

myApp.directive('myDirective', function() {

  return {
    template: '<div>{{ demo.myValue }}</div>',
    link: function($scope, $element, $attrs) {
      $attrs.$observe('type', function(value) {
        $element.removeClass();
        $element.addClass('alert alert-' + value);
      });
    }
  };
});

如果您确实需要双向绑定(允许您更新指令中的值),则可以使用$parse service。但在大多数情况下,您不需要这样,因为您无论如何都可以访问范围:

myApp.directive('myTwoWayDirective', function() {

  return {
    template: '<div>{{ demo.myValue }}' +
                '<select class="pull-right" ' +
                         'ng-model="demo.twoWayType" ' +
                         'ng-options="type for type in demo.types">' +
                '<select>' +
              '</div>',
    link: function($scope, $element, $attrs) {
      $scope.$watch('demo.twoWayType', function(value) {
        $element.removeClass();
        $element.addClass('alert alert-' + value);
      });
    }
  };
});

编辑:

新的plunker演示如何share data across angular components 和 一个额外的plunker可能会提供更多insight on directive scopes

答案 1 :(得分:0)

这很有效。我相信它可以做得更好。这让我的包含行为就像它们被内联写入页面一样,并且还可以通过templateReplace参数对它们进行一些独特的更改。

Log.directive 'logList', ($compile, $templateCache, $http) ->
    return {
        restrict: 'E'
        compile: (element, attr) ->
            return (scope, $element, $attr, ctrl) ->
                $http.get('/partials/log', {cache: $templateCache}).success (template) ->
                    template_replace = if $attr.templatereplace then $attr.templatereplace.split(',') else null
                    angular.forEach template_replace, (value, key) ->
                        template = template.replace '%replace%', value

                    content = $compile(template)(scope)
                    $element.html('')
                    $element.append(content)                
    }

以下是我正在使用的模板示例,只需要进行1次少量更改,但在我的应用的两个列中都是相同的:

div.row(ng-repeat="log in %replace% | prepare_log | orderBy: 'log.created'")
    div.log-wrapper(ng-class="log.level")
        a.pin(title="Pin this log message", ng-click="pin($index, %replace%)")

这是我实现指令的主要模板:

div.columns.small-6
    log-list(templateReplace="logs,1")

div.columns.small-6
    log-list(templateReplace="pinned,0")

编辑:

我实际上最终做了什么:

    div.columns.small-6
        div.row(ng-repeat="log in logs | prepare_log | orderBy: 'log.created'", ng-init="pin_or_unpin=1")
            ng-include(src="'/partials/log'")

部分:

div.log-wrapper(ng-class="log.level")
    a.pin(title="Pin this log message", ng-click="pin($index, pin_or_unpin)")

答案 2 :(得分:-1)

演示:http://plnkr.co/edit/mgiYWP

对于指令,即使它们来自保存构造函数,也没有简单的方法可以自动找到两个指令的通用范围。但您可以在return语句之前共享相同的变量。

app.directive('logList', function($compile, $templateCache) {

  var sharedScope;

  return {
    restrict: 'E',
    // scope: {
    //   type: '='
    // },
    templateUrl: "log.html",
    link: function(scope, element, attrs) {

      // create shared isolated scope if not defined yet
      if (typeof sharedScope === 'undefined') {
        sharedScope = scope.$new(true);

        // manual bi-directional binding for type attribute
        sharedScope.$watch(function() {
          return scope.$eval(attrs.type);
        }, function(val) {
          sharedScope.type = val;
        });
      }

      // recompile directive DOM content to sharedScope
      var template = $templateCache.get('log.html')[1];
      var newContent = $compile(template)(sharedScope);

      element.html('');
      element.append(newContent);
    }
  };

});

这应该为所有logList指令提供共享的隔离范围,但由于您共享隔离范围,因此您只能双向绑定首先实例化的指令中的type属性。 / p>