Associazione del metodo dell'elemento della direttiva AngularJS - TypeError: non è possibile utilizzare l'operatore 'in' per cercare 'functionName' in 1


90

Questo è il controller del template principale:

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

Questa è la direttiva:

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

Ecco come viene applicata la direttiva nel template principale:

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

e questo metodo è chiamato dal modello di direttiva (website-overview.html):

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

DOMANDA: Quando si fa clic su MODIFICA, nella console viene visualizzato questo errore:

TypeError: impossibile utilizzare l'operatore "in" per cercare "editWebsite" in 1

Qualcuno sa cosa succede qui?

Risposte:


178

Poiché hai definito un'espressione binding ( &), devi chiamarla esplicitamente con un JSON contenente il idse vuoi associarlo nell'HTML come edit-website="editWebsite(id)".

In effetti, Angular ha bisogno di capire di cosa si idtratta nel tuo HTML, e poiché non fa parte del tuo ambito, devi aggiungere quelli che vengono chiamati "locals" alla tua chiamata facendo:

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

O in alternativa:

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

Con il controller / codice collegamento:

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

Questo è documentato qui, cerca l'esempio che coinvolge "close({message: 'closing for now'})"

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


7
Grazie per la tua risposta e per aver indicato la posizione precisa sulla documentazione, è stato incredibilmente utile!
Bruno Belotti

1
@floribon So che è un po 'vecchio, ma hai un esempio di dattilografia della richiamata?
tcrite

È davvero utile, grazie.
Anurag pareek

ancora utile per le persone che lavorano su progetti legacy .. grazie
BMWCMW

4

TL; DR;- Stai assumendo che la funzione associata venga passata al componente figlio. Questo non è corretto. In effetti, AngularJS sta analizzando il modello di stringa e creando una nuova funzione, che quindi chiama la funzione padre.

Questa funzione deve ricevere un oggetto con chiavi e valori, piuttosto che una semplice variabile.

Spiegazione più lunga

Questo accade quando hai associato una funzione usando '&' e hai provato a chiamare quella funzione dal tuo controller, passando una semplice variabile piuttosto che un oggetto contenente il nome della semplice variabile. Le chiavi dell'oggetto sono necessarie al motore di modelli per capire come passare i valori nella funzione associata.

per esempio. hai chiamato boundFunction('cats')invece diboundFunction({value: 'cats'})

Esempio lavorato

Diciamo che creo un componente come questo:

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

Questa funzione (nel genitore) ha questo aspetto:

onSearch(value) {
  // do search
}

Nel mio modello genitore, ora posso farlo:

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

L'associazione qui verrà analizzata dalla stringa. In realtà non stai passando la funzione. AngularJS sta creando una funzione per te che chiama la funzione. L'associazione creata nel modello può contenere molte cose oltre alla chiamata di funzione.

AngularJS in qualche modo ha bisogno di capire da dove andare value, e lo fa ricevendo un oggetto dal genitore.

Nel controller myComponent, devo fare qualcosa come:

handleOnSearch(value) {
  if (this.onSearch) {
    this.onSearch({value: value})
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.