Elementmethodenbindung der AngularJS-Direktive – TypeError: Der Operator „in“ kann nicht verwendet werden, um in 1 nach „functionName“ zu suchen

Lesezeit: 3 Minuten

Benutzer-Avatar
CodeVirtuose

Dies ist der Controller der Hauptvorlage:

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

Dies ist die Richtlinie:

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

So wird die Richtlinie in der Hauptvorlage angewendet:

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

und diese Methode wird von der Direktivenvorlage (website-overview.html) aufgerufen:

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

FRAGE: Wenn BEARBEITEN angeklickt wird, erscheint dieser Fehler in der Konsole:

TypeError: Der „in“-Operator kann nicht verwendet werden, um in 1 nach „editWebsite“ zu suchen

Weiß jemand was hier los ist?

Benutzer-Avatar
Blumen

Da Sie eine Ausdrucksbindung definiert haben (&), müssen Sie es explizit mit einem Objektliteralparameter aufrufen, der enthält id wenn Sie es in HTML als binden möchten edit-website="editWebsite(id)".

In der Tat muss Angular verstehen, was das ist id befindet sich in Ihrem HTML, und da es nicht Teil Ihres Bereichs ist, müssen Sie Ihrem Aufruf so genannte “Lokale” hinzufügen, indem Sie Folgendes tun:

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

Oder alternativ:

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

Mit dem Controller/Link-Code:

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

AngularJS enthält eine Erklärung dazu in seiner Dokumentation; suchen Sie nach dem Beispiel mit "close({message: 'closing for now'})" unter folgender URL:

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

  • @floribon Ich weiß, das ist etwas alt, aber haben Sie ein Beispiel für das Schreiben des Rückrufs?

    – tcrite

    5. April 2017 um 15:09 Uhr

  • Oft ist es wünschenswert, Daten aus dem isolierenden Bereich über einen Ausdruck an den übergeordneten Bereich zu übergeben; Dies kann durch Übergeben einer Zuordnung lokaler Variablennamen und -werte an die Ausdrucks-Wrapper-Funktion erfolgen. Zum Beispiel die hideDialog Die Funktion nimmt eine Meldung an, die angezeigt wird, wenn das Dialogfeld ausgeblendet ist. Dies wird in der Direktive durch Aufruf angegeben close({message: 'closing for now'}). Dann die lokale Variable message wird innerhalb der verfügbar sein on-close Ausdruck.” [emph mine] Die Wahrheit ist seltsamer als die Fiktion. Ich würde gerne wissen, wie sie dies als die beste Lösung für Event-Handler ausgewählt haben.

    – Rufin

    13. Oktober 2020 um 19:39 Uhr

Benutzer-Avatar
superluminary

TL;DR; – Sie gehen davon aus, dass die gebundene Funktion an die untergeordnete Komponente übergeben wird, wie es in React der Fall wäre. Das ist falsch. Tatsächlich analysiert AngularJS die Zeichenfolgenvorlage und erstellt eine neue Funktion, die dann die übergeordnete Funktion aufruft.

Diese generierte Funktion erwartet statt einer einfachen Variablen den Empfang eines Objekts mit Schlüsseln und Werten.

Längere Erklärung

Dies passiert, wenn Sie eine Funktion mit ‘&’ gebunden haben und versucht haben, diese Funktion von Ihrem Controller aus aufzurufen, wobei Sie eine einfache Variable anstelle eines Objekts übergeben, das den Namen der einfachen Variablen enthält. Die Objektschlüssel werden von der Templating-Engine benötigt, um herauszufinden, wie Werte an die gebundene Funktion übergeben werden.

z.B. du hast angerufen boundFunction('cats') statt boundFunction({value: 'cats'})

Gearbeitetes Beispiel

Angenommen, ich erstelle eine Komponente wie diese:

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

Diese Funktion (im Elternteil) sieht so aus:

onSearch(value) {
  // do search
}

In meiner übergeordneten Vorlage kann ich jetzt Folgendes tun:

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

Die Bindung hier wird aus der Zeichenfolge geparst. Sie übergeben die Funktion nicht wirklich. AngularJS erstellt eine Funktion für Sie, die die Funktion aufruft. Die in der Vorlage erstellte Bindung kann viele andere Dinge als den Funktionsaufruf enthalten.

AngularJS muss irgendwie herausfinden, wo es hinkommt value from, und zwar durch Empfangen eines Objekts vom übergeordneten Element.

Im myComponent-Controller muss ich so etwas tun:

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

  • Okay, jemand dachte, dieser Kommentar sei überflüssig, obwohl er positiv bewertet wurde, also lass es mich noch einmal versuchen: Beachten Sie, dass der Kern dieser Antwort lautet:du hast angerufen boundFunction('cats') statt boundFunction({value: 'cats'})

    – Rufin

    25. Juni 2021 um 15:17 Uhr


1174940cookie-checkElementmethodenbindung der AngularJS-Direktive – TypeError: Der Operator „in“ kann nicht verwendet werden, um in 1 nach „functionName“ zu suchen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy