อัพเดตตัวแปรขอบเขตหลักใน AngularJS


113

ฉันมีตัวควบคุมสองตัวตัวหนึ่งห่อหุ้มไว้ด้วยกัน ตอนนี้ฉันรู้ว่าขอบเขตลูกสืบทอดคุณสมบัติจากขอบเขตหลัก แต่มีวิธีอัปเดตตัวแปรขอบเขตหลักหรือไม่ จนถึงตอนนี้ฉันยังไม่พบวิธีแก้ปัญหาที่ชัดเจน

ในสถานการณ์ของฉันฉันมีตัวควบคุมปฏิทินในแบบฟอร์ม ฉันต้องการอัปเดตวันที่เริ่มต้นและวันที่สิ้นสุดจากขอบเขตหลัก (ซึ่งก็คือแบบฟอร์ม) เพื่อให้แบบฟอร์มมีวันที่เริ่มต้นและวันที่สิ้นสุดเมื่อส่ง


ดูเหมือนว่าตัวควบคุมปฏิทินของคุณควรเป็นคำสั่ง
โยนาห์

คำตอบ:


193

คุณต้องใช้วัตถุ (ไม่ใช่ดั้งเดิม) ในขอบเขตหลักจากนั้นคุณจะสามารถอัปเดตได้โดยตรงจากขอบเขตลูก

ต้นทาง:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

เด็ก:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

การสาธิตการทำงาน : http://jsfiddle.net/sh0ber/xxNxj/

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


1
ฉันได้รับข้อผิดพลาดนี้เมื่อพยายามใช้สิ่งนี้: 'ไม่สามารถตั้งค่าคุณสมบัติ' parentproperty 'ของไม่ได้กำหนด'
Malcr001

คุณสามารถโพสต์รหัสของคุณได้หรือไม่? มันทำงานในการสาธิตซอ หากการควบคุมปฏิทินของคุณใช้ขอบเขตการแยกการควบคุมจะไม่สืบทอดมาจากขอบเขตหลักดังนั้นคุณจะต้องส่งต่อค่าไปยังขอบเขตของคำสั่ง
แดน

ขออภัยฉันลืมคำถามนี้ ฉันยอมรับมันเพราะในที่สุดฉันก็สามารถทำให้มันทำงานได้ด้วยความช่วยเหลือของคำตอบนี้
Malcr001

ฉันเข้าใจว่าการใส่ {{parentobj.parentproperty}} ในองค์ประกอบ ctrlParent div คือสิ่งที่ประกาศออบเจ็กต์ parentobj และตั้งค่าออบเจ็กต์นี้ว่าอยู่ในขอบเขต ctrlParent นี่เป็นสมมติฐานที่ถูกต้องหรือไม่?
Stephane

1
ขอบคุณมันได้ผล! ฉันควรอ่านเรื่องนี้อย่างแน่นอน (สภาพแวดล้อมต้นแบบและดั้งเดิม) คุณช่วยแนะนำการอ่านดีๆที่อธิบายมากกว่าลิงค์ SO ของคุณได้ไหม
jvannistelrooy

116

มีอีกวิธีหนึ่งในการทำงานนี้และไม่ใช้$scope.$parentตัวแปร

เพียงเตรียมวิธีการเปลี่ยนค่าในขอบเขตหลักและใช้ในขอบเขตลูก แบบนี้:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

นอกจากนี้ยังทำงานและให้คุณควบคุมการเปลี่ยนแปลงค่าได้มากขึ้น

จากนั้นคุณสามารถยังเรียกวิธีแม้ใน HTML <a ng-click="changeSimpleValue('y')" href="#">click me!</a>ที่ชอบ:


1
ทางออกที่ดี! ใช้งานได้เนื่องจากเมื่อไม่พบบางสิ่งในขอบเขต $ ปัจจุบัน Angular จะค้นหาใน $ parent one docs.angularjs.org/guide/scope (ดู 'ลำดับชั้นขอบเขต')
Elo

ฉันชอบคำตอบนี้ไม่จำเป็นต้องสร้างวัตถุที่ไม่จำเป็น
grimmdude

3
ผู้อ่านในอนาคต: ความคิดเห็นระดับสูงทั้งห้าเหล่านี้มีความเข้าใจผิดเล็กน้อย การสร้างฟังก์ชัน setter สองฟังก์ชัน (ซึ่งเป็น "อ็อบเจ็กต์ที่ไม่จำเป็น") สำหรับทุกตัวแปรเป็นการสืบทอดที่ไม่จำเป็นและไม่จำเป็นและไม่ใช่วิธีเชิงมุม Misko Hevery ผู้สร้าง Angular ได้พูดถึงเขาสอนว่า "เมื่อใดก็ตามที่คุณมี ng-model จะต้องมีจุดอยู่ที่นั่นที่ไหนสักแห่งหากคุณไม่มีจุดแสดงว่าคุณทำผิด" วิดีโอ Misko @ 29:19
Dan

ฉันจะใช้โซลูชันนี้โดยใช้ไวยากรณ์ controllerAS ได้อย่างไร
นิรัน

6

วิธีนี้ใช้งานได้เช่นกัน (แต่ไม่แน่ใจว่าเป็นไปตามแนวทางปฏิบัติที่ดีที่สุดหรือไม่)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});

1
คุณถูกต้องโดยใช้ $ scope $ parent.value จะใช้ได้ผลในกรณีส่วนใหญ่อย่างไรก็ตามโดยปกติแล้วไม่ใช่ความคิดที่ดีที่สุดที่จะใช้อย่างกว้างขวางเนื่องจากอาจทำให้ยากต่อการจัดการในโครงการที่ใหญ่กว่าและซับซ้อนกว่า
Alex Johnson

4

เมื่อคุณกำหนดแอตทริบิวต์ดั้งเดิมให้กับขอบเขตขอบเขตนั้นจะอยู่ภายในขอบเขตเสมอ (อาจสร้างขึ้นได้ทันที) แม้ว่าขอบเขตหลักจะมีแอตทริบิวต์ที่มีชื่อเดียวกันก็ตาม นี่เป็นการตัดสินใจในการออกแบบและเป็น IMHO ที่ดี

หากคุณต้องการเปลี่ยนพื้นฐานบางอย่าง (ints, booleans, strings) ในขอบเขตหลักจากมุมมองคุณจะต้องเป็นแอตทริบิวต์ของออบเจ็กต์อื่นในขอบเขตนั้นดังนั้นการกำหนดอาจอ่าน:

<a ng-click="viewData.myAttr = 4">Click me!</a>

และในทางกลับกัน:

  1. รับไฟล์ viewDataวัตถุจากขอบเขตที่กำหนดไว้
  2. กำหนด 4 ให้กับmyAttrแอตทริบิวต์

4

สำหรับการเข้าถึงตัวแปรที่ประกาศใน parent เราควรใช้ $ parent ใน child controller หรือ template file

ในตัวควบคุม

$scope.$parent.varaiable_name

ในเทมเพลต html

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