วิธีเข้าถึงขอบเขตพาเรนต์จากภายในคำสั่งที่กำหนดเอง * ด้วยขอบเขตของตัวเอง * ใน AngularJS


327

ฉันกำลังมองหาวิธีการเข้าถึงขอบเขต "หลัก" ใด ๆ ภายในคำสั่ง การรวมกันของขอบเขต, transclude, ต้อง, ผ่านในตัวแปร (หรือขอบเขตของตัวเอง) จากด้านบน ฯลฯ ฉันยินดีที่จะโค้งไปข้างหลังทั้งหมด แต่ฉันต้องการที่จะหลีกเลี่ยงบางสิ่งบางอย่างโดยสิ้นเชิงแฮ็คหรือ unmaintainable ตัวอย่างเช่นฉันรู้ว่าฉันสามารถทำได้ทันทีโดยรับ$scopeจากพารามิเตอร์ preLink และวนซ้ำตาม$siblingขอบเขตเพื่อค้นหาแนวคิด "หลัก"

สิ่งที่ฉันต้องการคือการสามารถ$watchแสดงออกในขอบเขตผู้ปกครอง หากฉันสามารถทำสิ่งนั้นได้ฉันก็สามารถทำสิ่งที่ฉันพยายามทำที่นี่ได้: AngularJS - การสร้างตัวแปรบางส่วนด้วยวิธีการได้อย่างไร?

หมายเหตุสำคัญคือคำสั่งนั้นจะต้องสามารถใช้งานได้อีกครั้งภายในขอบเขตหลักเดียวกัน ดังนั้นพฤติกรรมเริ่มต้น (ขอบเขต: false) จึงไม่ทำงานสำหรับฉัน ฉันต้องการแต่ละขอบเขตต่ออินสแตนซ์ของคำสั่งและจากนั้นฉันต้องการ$watchตัวแปรที่อยู่ในขอบเขตพาเรนต์

ตัวอย่างโค้ดมีค่า 1,000 คำดังนั้น:

app.directive('watchingMyParentScope', function() {
    return {
        require: /* ? */,
        scope: /* ? */,
        transclude: /* ? */,
        controller: /* ? */,
        compile: function(el,attr,trans) {
            // Can I get the $parent from the transclusion function somehow?
            return {
                pre: function($s, $e, $a, parentControl) {
                    // Can I get the $parent from the parent controller?
                    // By setting this.$scope = $scope from within that controller?

                    // Can I get the $parent from the current $scope?

                    // Can I pass the $parent scope in as an attribute and define
                    // it as part of this directive's scope definition?

                    // What don't I understand about how directives work and
                    // how their scope is related to their parent?
                },
                post: function($s, $e, $a, parentControl) {
                    // Has my situation improved by the time the postLink is called?
                }
            }
        }
    };
});

คำตอบ:


644

ดูความแตกต่างของขอบเขตการสืบทอดต้นแบบ / การสร้างต้นแบบใน AngularJS คืออะไร

ในการสรุป: วิธีที่ directive เข้าถึง$parentขอบเขตparent ( ) จะขึ้นอยู่กับประเภทของขอบเขตที่ directive สร้างขึ้น:

  1. default ( scope: false) - คำสั่งไม่ได้สร้างขอบเขตใหม่ดังนั้นจึงไม่มีการสืบทอดที่นี่ ขอบเขตของไดเรกทีฟคือขอบเขตเดียวกับพาเรนต์ / คอนเทนเนอร์ ในฟังก์ชั่นลิงค์ใช้พารามิเตอร์แรก (โดยทั่วไปscope)

  2. scope: true- คำสั่งสร้างขอบเขตลูกใหม่ที่ต้นแบบสืบทอดมาจากขอบเขตแม่ คุณสมบัติที่กำหนดไว้ในขอบเขตพาเรนต์มีอยู่ในคำสั่งscope(เนื่องจากการสืบทอดต้นแบบ) เพียงระวังการเขียนไปยังคุณสมบัติขอบเขตดั้งเดิม - ที่จะสร้างคุณสมบัติใหม่บนขอบเขตคำสั่ง (ที่ซ่อน / เงาคุณสมบัติขอบเขตหลักในชื่อเดียวกัน)

  3. scope: { ... }- คำสั่งสร้างขอบเขตแยก / แยกใหม่ มันไม่ได้สืบทอดขอบเขตของ parent prototypically คุณยังคงสามารถเข้าถึงขอบเขตพาเรน$parentต์ที่ใช้ได้ แต่โดยปกติจะไม่แนะนำ แต่คุณควรระบุคุณสมบัติขอบเขตพ่อแม่ (และ / หรือฟังก์ชั่น) ความต้องการสั่งผ่านทางคุณลักษณะเพิ่มเติมเกี่ยวกับองค์ประกอบเดียวกับที่สั่งถูกนำมาใช้โดยใช้=, @และ&สัญกรณ์

  4. transclude: true- คำสั่งจะสร้างขอบเขตย่อย "transcluded" ใหม่ซึ่งสืบทอดจากต้นแบบแม่ขอบเขต หากคำสั่งสร้างขอบเขตไอโซเลตด้วย transcluded และขอบเขตไอโซเลตจะเป็นพี่น้องกัน $parentคุณสมบัติของแต่ละขอบเขตอ้างอิงขอบเขตแม่เดียวกัน
    การอัปเดต Angular v1.3 : หากคำสั่งสร้างขอบเขต isolate ด้วยขอบเขต transcluded จะกลายเป็นลูกของขอบเขต isolate ขอบเขตที่แยกและแยกออกจะไม่เป็นพี่น้องอีกต่อไป $parentทรัพย์สินของขอบเขตเรียกในขณะนี้อ้างอิงขอบเขตแยก

ลิงค์ด้านบนมีตัวอย่างและรูปภาพทั้ง 4 ประเภท

คุณไม่สามารถเข้าถึงขอบเขตในฟังก์ชั่นการคอมไพล์ของคำสั่ง (ดังที่กล่าวไว้ที่นี่: https://github.com/angular/angular.js/wiki/Understanding-Directives ) คุณสามารถเข้าถึงขอบเขตของไดเรกทีฟในฟังก์ชันลิงก์

ดู:

สำหรับ 1. และ 2. ด้านบน: โดยปกติคุณจะต้องระบุคุณสมบัติหลักที่คุณสมบัติความต้องการผ่านคุณสมบัติจากนั้น $ เฝ้าดู:

<div my-dir attr1="prop1"></div>

scope.$watch(attrs.attr1, function() { ... });

หากคุณกำลังดูคุณสมบัติออบเจกต์คุณจะต้องใช้การแยกวิเคราะห์ $:

<div my-dir attr2="obj.prop2"></div>

var model = $parse(attrs.attr2);
scope.$watch(model, function() { ... });

สำหรับ 3. ข้างต้น (แยกขอบเขต) ให้ดูชื่อที่คุณให้คุณสมบัติคำสั่งโดยใช้เครื่องหมาย@หรือ=:

<div my-dir attr3="{{prop3}}" attr4="obj.prop4"></div>

scope: {
  localName3: '@attr3',
  attr4:      '='  // here, using the same name as the attribute
},
link: function(scope, element, attrs) {
   scope.$watch('localName3', function() { ... });
   scope.$watch('attr4',      function() { ... });

1
ขอบคุณทำเครื่องหมาย มันกลับกลายเป็นว่าฉันโพสต์ลงบนวิธีการทำให้บางส่วนกับตัวแปรทำงานได้ค่อนข้างสวยงาม สิ่งที่คุณต้องการในการเชื่อมโยงฉันเป็นสิ่งที่มีชื่อว่า "ความแตกต่างของการเขียน HTML และตระหนักว่าองค์ประกอบของคุณไม่ได้ซ้อนอยู่ภายในตัวควบคุม ng ที่คุณคิดว่าเป็น" ว้าว ... ความผิดพลาดหน้าใหม่ แต่นี่เป็นส่วนเสริมที่มีประโยชน์สำหรับคำตอบอื่น ๆ ของคุณ (นานกว่า) อธิบาย
colllin

@ คอลลินเยี่ยมมากฉันดีใจที่คุณแก้ไขปัญหาของคุณเนื่องจากฉันไม่แน่ใจว่าจะตอบความคิดเห็นของคุณ (ลบแล้ว) ในขณะนี้ได้อย่างไร
Mark Rajcok

อะไรสิ่งที่สามารถ / ฉันควรจะดำเนินการภายในscope.$watch('localName3', function() { ...[?? WHAT TO DO HERE for example?] });
Junaid กอดีร์

1
@Andy ไม่มีไม่ได้ใช้$parseกับ=: ซอ $parseจำเป็นเฉพาะกับขอบเขตที่ไม่แยก
Mark Rajcok

1
นี่คือคำตอบที่ดีอย่างละเอียดมาก มันยังแสดงให้เห็นว่าทำไมฉันเกลียดการทำงานกับ AngularJS
John Trichereau

51

การเข้าถึงวิธีการควบคุมหมายถึงการเข้าถึงวิธีการในขอบเขตหลักจาก directive controller / link / scope

หากคำสั่งใช้การแชร์ / การสืบทอดขอบเขตพาเรนต์มันจะค่อนข้างตรงไปข้างหน้าเพียงแค่เรียกใช้เมธอดขอบเขตขอบเขต

จำเป็นต้องใช้งานอีกเล็กน้อยเมื่อคุณต้องการเข้าถึงวิธีขอบเขตหลักจากขอบเขตคำสั่งแบบแยก

มีตัวเลือกน้อย (อาจมากกว่ารายการด้านล่าง) เพื่อเรียกใช้วิธีขอบเขตของพาเรนต์จากขอบเขตคำสั่งแยกหรือดูตัวแปรขอบเขตพาเรนต์ ( ตัวเลือก # 6พิเศษ)

โปรดทราบว่าฉันใช้link functionในตัวอย่างเหล่านี้ แต่คุณสามารถใช้directive controllerเช่นกันตามความต้องการ

ตัวเลือกที่ 1. ผ่าน Object แท้จริงและจากแม่แบบคำสั่ง HTML

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>

    <p> Directive Content</p>
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter>


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>

  </body>

</html>

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChanged({selectedItems:selectedItems})" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>

app.js

var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=',
      selectedItemsChanged: '&'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.selectedItemsChanged = function(selectedItems1) {
    $scope.selectedItemsReturnedFromDirective = selectedItems1;
  }

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]

});

การทำงานของ plnkr: http://plnkr.co/edit/rgKUsYGDo9O3tewL6xgr?p=preview

# 2 ตัวเลือก ผ่าน Object แท้จริงและจากลิงค์ / ขอบเขตคำสั่ง

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>

    <p> Directive Content</p>
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter>


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>

  </body>

</html>

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>

app.js

var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=',
      selectedItemsChanged: '&'
    },
    templateUrl: "itemfilterTemplate.html",
    link: function (scope, element, attrs){
      scope.selectedItemsChangedDir = function(){
        scope.selectedItemsChanged({selectedItems:scope.selectedItems});  
      }
    }
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.selectedItemsChanged = function(selectedItems1) {
    $scope.selectedItemsReturnedFromDirective = selectedItems1;
  }

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

การทำงานของ plnkr: http://plnkr.co/edit/BRvYm2SpSpBK9uxNIcTa?p=preview

ตัวเลือกที่ 3 ผ่านการอ้างอิงฟังก์ชั่นและจากแม่แบบคำสั่ง html

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>

    <p> Directive Content</p>
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnFromDirective}} </p>

  </body>

</html>

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-change="selectedItemsChanged()(selectedItems)" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>

app.js

var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems:'=',
      selectedItemsChanged: '&'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.selectedItemsChanged = function(selectedItems1) {
    $scope.selectedItemsReturnFromDirective = selectedItems1;
  }

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

การทำงานของ plnkr: http://plnkr.co/edit/Jo6FcYfVXCCg3vH42BIz?p=preview

# 4 ตัว ผ่านการอ้างอิงฟังก์ชั่นและจากลิงค์ / ขอบเขตคำสั่ง

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>

    <p> Directive Content</p>
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p>

  </body>

</html>

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>

app.js

var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=',
      selectedItemsChanged: '&'
    },
    templateUrl: "itemfilterTemplate.html",
    link: function (scope, element, attrs){
      scope.selectedItemsChangedDir = function(){
        scope.selectedItemsChanged()(scope.selectedItems);  
      }
    }
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.selectedItemsChanged = function(selectedItems1) {
    $scope.selectedItemsReturnedFromDirective = selectedItems1;
  }

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]

});

การทำงานของ plnkr: http://plnkr.co/edit/BSqx2J1yCY86IJwAnQF1?p=preview

ตัวเลือก # 5: ผ่าน ng-model และการโยงสองทางคุณสามารถอัพเดตตัวแปรขอบเขตพาเรนต์ . ดังนั้นคุณอาจไม่จำเป็นต้องเรียกใช้ฟังก์ชันขอบเขตหลักในบางกรณี

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{name}}!</p>

    <p> Directive Content</p>
    <sd-items-filter ng-model="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter>


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}} </p>

  </body>

</html>

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>

app.js

var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=ngModel'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

การทำงานของ plnkr: http://plnkr.co/edit/hNui3xgzdTnfcdzljihY?p=preview

ตัวเลือก # 6: ผ่าน$watchและ$watchCollection เป็นการผูกมัดสองทางitemsในตัวอย่างด้านบนทั้งหมดหากรายการถูกแก้ไขในขอบเขตพาเรนต์รายการในคำสั่งจะสะท้อนถึงการเปลี่ยนแปลงด้วย

หากคุณต้องการดูคุณสมบัติหรือวัตถุอื่น ๆ จากขอบเขตหลักคุณสามารถทำได้โดยใช้$watchและ$watchCollectionตามที่ระบุด้านล่าง

HTML

<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <p>Hello {{user}}!</p>
  <p>directive is watching name and current item</p>
  <table>
    <tr>
      <td>Id:</td>
      <td>
        <input type="text" ng-model="id" />
      </td>
    </tr>
    <tr>
      <td>Name:</td>
      <td>
        <input type="text" ng-model="name" />
      </td>
    </tr>
    <tr>
      <td>Model:</td>
      <td>
        <input type="text" ng-model="model" />
      </td>
    </tr>
  </table>

  <button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button>

  <p>Directive Contents</p>
  <sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter>

  <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p>
</body>

</html>

สคริปต์ app.js

var app = angular.module ('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      name: '@',
      currentItem: '=',
      items: '=',
      selectedItems: '=ngModel'
    },
    template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' +
      'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' +
      '<option>--</option> </select>',
    link: function(scope, element, attrs) {
      scope.$watchCollection('currentItem', function() {
        console.log(JSON.stringify(scope.currentItem));
      });
      scope.$watch('name', function() {
        console.log(JSON.stringify(scope.name));
      });
    }
  }
})

 app.controller('MainCtrl', function($scope) {
  $scope.user = 'World';

  $scope.addItem = function() {
    $scope.items.push({
      id: $scope.id,
      name: $scope.name,
      model: $scope.model
    });
    $scope.currentItem = {};
    $scope.currentItem.id = $scope.id;
    $scope.currentItem.name = $scope.name;
    $scope.currentItem.model = $scope.model;
  }

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
  }]
});

คุณสามารถอ้างอิงเอกสารของ AngularJs สำหรับคำอธิบายโดยละเอียดเกี่ยวกับคำสั่ง


10
เขาทำงานหนักเพื่อตัวแทนของเขา ... ยากสำหรับตัวแทนของเขา ... เขาทำงานหนักเพื่อตัวแทนของเขาเพื่อให้คุณดีกว่าโหวตให้เขาถูกต้อง
บาง

7
downvoted - ข้อมูลที่มีค่าใด ๆ ในคำตอบนั้นไม่สามารถเข้าถึงได้เนื่องจากความยาวของมัน
แก้ไข

2
ฉันตอบคำถามด้วยทางเลือกที่มีทั้งหมดพร้อมการแยกที่ชัดเจน ในความคิดของฉันคำตอบสั้น ๆ ไม่ได้มีประโยชน์เสมอไปจนกว่าคุณจะได้เห็นภาพต่อหน้าคุณ
Yogesh Manware

@YogeshManware: มันสั้นลงมากโดยทิ้งสิ่งที่ไม่เกี่ยวข้องเช่น stylesheets ไม่ใช้มาร์กอัปที่มีความยาวทำให้ตัวอย่างง่ายขึ้นที่จะไม่ใช้สิ่งต่าง ๆ เช่น "group by" เป็นต้นมันจะมีประโยชน์มากสำหรับคำอธิบายบางอย่างสำหรับ แต่ละตัวอย่าง
damd

นี่ไม่ใช่เหตุผลที่จะลงคะแนน ผู้คนละเมิดสิทธิพิเศษนี้
Winnemucca

11
 scope: false
 transclude: false

และคุณจะมีขอบเขตเดียวกัน (พร้อมองค์ประกอบหลัก)

$scope.$watch(...

มีหลายวิธีในการเข้าถึงขอบเขตพาเรนต์โดยขึ้นอยู่กับขอบเขตของตัวเลือกสองตัวนี้ & transclude


ใช่สั้นและหวานและถูกต้อง ดูเหมือนว่าพวกเขาจะแบ่งปันขอบเขตเดียวกับองค์ประกอบหลักแม้ว่า ... ซึ่งทำให้พวกเขาไม่สามารถนำกลับมาใช้ในขอบเขตเดียวกันได้อีก jsfiddle.net/collindo/xqytH
colllin

2
หลายครั้งที่เราต้องการขอบเขตแยกเมื่อเราเขียนส่วนประกอบที่นำกลับมาใช้ใหม่ได้ดังนั้นวิธีแก้ปัญหาก็ไม่ง่ายเช่นนี้
Yvon Huynh

8

นี่คือเคล็ดลับที่ฉันใช้ครั้งเดียว: สร้างคำสั่ง "ดัมมี่" เพื่อเก็บขอบเขตของผู้ปกครองและวางไว้ที่ไหนสักแห่งนอกคำสั่งที่ต้องการ สิ่งที่ต้องการ:

module.directive('myDirectiveContainer', function () {
    return {
        controller: function ($scope) {
            this.scope = $scope;
        }
    };
});

module.directive('myDirective', function () {
    return {
        require: '^myDirectiveContainer',
        link: function (scope, element, attrs, containerController) {
            // use containerController.scope here...
        }
    };
});

แล้ว

<div my-directive-container="">
    <div my-directive="">
    </div>
</div>

อาจไม่ใช่โซลูชันที่สง่างามที่สุด แต่ทำงานได้สำเร็จ


4

หากคุณใช้คลาส ES6 และControllerAsไวยากรณ์คุณต้องทำสิ่งที่แตกต่างออกไปเล็กน้อย

ดูตัวอย่างด้านล่างและทราบว่าvmเป็นControllerAsค่าของการควบคุมหลักที่ใช้ใน HTML แม่

myApp.directive('name', function() {
  return {
    // no scope definition
    link : function(scope, element, attrs, ngModel) {

        scope.vm.func(...)

0

เมื่อได้ลองทุกอย่างในที่สุดฉันก็คิดวิธีแก้ปัญหา

เพียงวางสิ่งต่อไปนี้ในเทมเพลตของคุณ:

{{currentDirective.attr = parentDirective.attr; ''}}

เป็นเพียงการเขียนแอตทริบิวต์ / ตัวแปรขอบเขตหลักที่คุณต้องการเข้าถึงขอบเขตปัจจุบัน

นอกจากนี้สังเกตว่า; ''ในตอนท้ายของคำสั่งนั้นเพื่อให้แน่ใจว่าไม่มีผลลัพธ์ในเทมเพลตของคุณ (เชิงมุมประเมินทุกคำสั่ง แต่ให้ผลลัพธ์ล่าสุดเท่านั้น)

มันค่อนข้างแฮ็ค แต่หลังจากผ่านการลองผิดลองถูกไปสองสามชั่วโมงมันก็ทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.