AngularJS Directive element การผูก - TypeError: ไม่สามารถใช้ตัวดำเนินการ 'in' เพื่อค้นหา 'functionName' ใน 1


92

นี่คือตัวควบคุมของเทมเพลตหลัก:

app.controller('OverviewCtrl', ['$scope', '$location', '$routeParams', 'websiteService', 'helperService', function($scope, $location, $routeParams, websiteService, helperService) {
    ...     
    $scope.editWebsite = function(id) {
        $location.path('/websites/edit/' + id);
    };
}]);

นี่คือคำสั่ง:

app.directive('wdaWebsitesOverview', function() {
    return {
        restrict: 'E',
        scope: {
            heading: '=',
            websites: '=',
            editWebsite: '&'
        },
        templateUrl: 'views/websites-overview.html'
    }
});

นี่คือวิธีใช้คำสั่งในเทมเพลตหลัก:

<wda-websites-overview heading="'All websites'" websites="websites" edit-website="editWebsite(id)"></wda-websites-overview>

และนี่คือเมธอดถูกเรียกจากเทมเพลตคำสั่ง (เว็บไซต์ภาพรวม.html):

<td data-ng-click="editWebsite(website.id)">EDIT</td>

คำถาม: เมื่อคลิก EDIT ข้อผิดพลาดนี้จะปรากฏในคอนโซล:

TypeError: ไม่สามารถใช้ตัวดำเนินการ 'in' เพื่อค้นหา 'editWebsite' ใน 1

มีใครรู้บ้างว่าเกิดอะไรขึ้นที่นี่?

คำตอบ:


180

ตั้งแต่คุณกำหนดไว้การแสดงออกที่มีผลผูกพัน ( &), คุณจำเป็นต้องเรียกอย่างชัดเจนกับวัตถุพารามิเตอร์ตัวอักษรที่มีidถ้าคุณต้องการที่จะลงนามผูกพันใน HTML edit-website="editWebsite(id)"เป็น

อันที่จริง Angular จำเป็นต้องเข้าใจว่าสิ่งนี้idคืออะไรใน HTML ของคุณและเนื่องจากไม่ได้เป็นส่วนหนึ่งของขอบเขตของคุณคุณจึงต้องเพิ่มสิ่งที่เรียกว่า "คนในท้องถิ่น" ในการเรียกของคุณโดยทำ:

data-ng-click="editWebsite({id: website.id})"

หรือเป็นทางเลือก:

data-ng-click="onClick(website.id)"

ด้วยรหัสคอนโทรลเลอร์ / ลิงค์:

$scope.onClick = function(id) {
  // Ad "id" to the locals of "editWebsite" 
  $scope.editWebsite({id: id});
}

AngularJS มีคำอธิบายในเอกสารประกอบ ค้นหาตัวอย่างที่เกี่ยวข้องกับ"close({message: 'closing for now'})"URL ต่อไปนี้:

https://docs.angularjs.org/guide/directive


7
ขอบคุณสำหรับคำตอบของคุณและสำหรับการชี้ตำแหน่งที่แม่นยำในเอกสารมันเป็นประโยชน์อย่างไม่น่าเชื่อ
Bruno Belotti

1
@floribon ฉันรู้ว่ามันเก่า แต่คุณมีตัวอย่างของการพิมพ์ข้อความเรียกกลับหรือไม่?
tcrite

มันมีประโยชน์มากขอบคุณ
Anurag pareek

ยังคงมีประโยชน์สำหรับคนที่ทำงานในโครงการเดิม .. ขอบคุณ
BMWCMW

" บ่อยครั้งเป็นที่พึงปรารถนาที่จะส่งผ่านข้อมูลจากขอบเขตการแยกผ่านนิพจน์ไปยังขอบเขตพาเรนต์ซึ่งสามารถทำได้โดยส่งแผนที่ชื่อตัวแปรโลคัลและค่าไปยังฟังก์ชัน wrapper นิพจน์ตัวอย่างเช่นhideDialogฟังก์ชันรับข้อความเพื่อแสดงเมื่อ กล่องโต้ตอบถูกซ่อนไว้ซึ่งระบุไว้ในคำสั่งโดยการเรียกclose({message: 'closing for now'})จากนั้นตัวแปรท้องถิ่นmessageจะพร้อมใช้งานภายในon-closeนิพจน์ "[emph mine] ความจริงแปลกกว่านิยาย ฉันต้องการทราบว่าพวกเขาเลือกสิ่งนี้เป็นทางออกที่ดีที่สุดสำหรับตัวจัดการเหตุการณ์ได้อย่างไร
ruffin

7

TL; DR; - คุณสมมติว่าฟังก์ชันที่ถูกผูกไว้กำลังถูกส่งต่อไปยังองค์ประกอบลูก สิ่งนี้ไม่ถูกต้อง ในความเป็นจริง AngularJS กำลังแยกวิเคราะห์เทมเพลตสตริงและสร้างฟังก์ชันใหม่ซึ่งจะเรียกใช้ฟังก์ชันหลัก

ฟังก์ชันนี้จำเป็นต้องรับวัตถุที่มีคีย์และค่าแทนที่จะเป็นตัวแปรธรรมดา

คำอธิบายที่ยาวขึ้น

สิ่งนี้เกิดขึ้นเมื่อคุณผูกฟังก์ชันโดยใช้ '&' และพยายามเรียกใช้ฟังก์ชันนั้นจากคอนโทรลเลอร์ของคุณโดยส่งผ่านตัวแปรธรรมดาแทนที่จะเป็นอ็อบเจ็กต์ที่มีชื่อของตัวแปรธรรมดา Templating Engine ต้องการคีย์ออบเจ็กต์เพื่อหาวิธีส่งค่าไปยังฟังก์ชันที่ถูกผูกไว้

เช่น. คุณได้โทรหาboundFunction('cats')มากกว่าboundFunction({value: 'cats'})

ตัวอย่างการทำงาน

สมมติว่าฉันสร้างส่วนประกอบดังนี้:

const MyComponent = {
  bindings: {
    onSearch: '&'
  },
  controller: controller
};

ฟังก์ชันนี้ (ในพาเรนต์) มีลักษณะดังนี้:

onSearch(value) {
  // do search
}

ในเทมเพลตหลักของฉันตอนนี้ฉันสามารถทำได้:

<my-component on-search="onSearch(value)"></my-component>

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

AngularJS จำเป็นต้องคำนวณว่าจะได้รับvalueจากที่ใดและทำได้โดยการรับวัตถุจากผู้ปกครอง

ในตัวควบคุม myComponent ฉันต้องทำสิ่งต่างๆเช่น:

handleOnSearch(value) {
  if (this.onSearch) {
    this.onSearch({value: value})
  }
}

1
moneyball แน่นอน; ขอบคุณ: " คุณโทรหาboundFunction('cats')มากกว่าboundFunction({value: 'cats'}) "
ruffin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.