2014-01-09 54 views
0

我做了包括指令像這樣:使指令使用父範圍?

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

我包括兩次在頁面上,並想都使用他們包括在根範圍。自從將這個重複的HTML放入包含中之後,我必須像$ parent。$ parent.something那樣做雜亂的東西。

回答

1

AngularJS會創建一個隔離範圍。顧名思義,這個獨立的作用域不會從父作用域繼承,因此不能直接訪問父作用域值。

但是,根據具體情況,可以通過多種方式訪問​​父級作用域屬性,而不使用容易出錯的錯誤$ parent

Plunker Demo

例如通過觀察屬性的值我們自己,我們不需要創建一個孤立的範圍,因此,我們可以訪問所有的容器範圍的屬性:如果你真的需要一個雙向綁定

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

+0

這將如何讓我通過一個獨特的參數到每個指令?現在我傳遞一個不同的類型,所以在include中我可以這樣做:div.row(ng-repeat =「登錄$ parent [type] | prepare_log | orderBy:'log.created'」) – Joren

+0

Just use從attrs參數中的$ observe方法,將它的值賦值給指令的作用域,並且該表達式將起作用。但是(** !! **)...您應該儘量避免使用$ parent,並且絕對不需要在共享範圍內進行破解,在每個鏈接上編譯一個額外的模板並將該模板重新鏈接到共享範圍:)我將添加一個新的plunker。 – null

+0

我對我所需要的東西的理解,以及我所要求的東西越來越多,因爲我看着角度的包含來源,以及你和戴維的東西。我想我確切地知道我需要什麼,但是如果你能就我發佈的解決方案給我看法,我會很感激。 – Joren

-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屬性。只要您在指定的範圍內領域的指令聲明什麼

+0

他們實際上包含在相同的控制器,所以他們已經共享父範圍。我想要做的就是將它們「透明地」包含進來,並且像我將它們直接放在模板中一樣,而不是在它們自己的繼承範圍中。 – Joren

+0

@Joren我剛剛更新了答案,我不知道這是你想要的。 – Daiwei

+0

這看起來可能有效。我可以用我的模塊的main $範圍編譯指令,而不是新的共享範圍嗎? – Joren

0

This works。我相信它可以做得更好,但。這讓我包含的行爲就像它們被內聯寫入頁面一樣,並且可以通過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)") 
+0

如果可行,它可以工作......但是不需要搜索並替換模板緩存並重新編譯它。 Angular可以以更清潔和高效的方式爲您做到這一切。例如,%replace%佔位符可以是範圍內的變量(也可以通過屬性提供給指令)。 我在答案中添加了一個[new plunker](http://plnkr.co/edit/bNJtOP?p=preview),也許這會給你更多的見解。 – null

+0

那個笨蛋很棒,並且演示了我需要的東西。事實證明,我做得比需要的要難得多。當我在包含內部執行ng-repeat時,我失去了範圍,並且必須做$ parent,$ parent,$ parent等。當我在include之外移動ng-repeat時,它一切正常,讓我做一個簡單的ng-init爲include設置我的自定義值。感謝您幫助我解決這個問題。 – Joren