Este es el controlador de la plantilla principal:
app.controller('OverviewCtrl', ['$scope', '$location', '$routeParams', 'websiteService', 'helperService', function($scope, $location, $routeParams, websiteService, helperService) { ... $scope.editWebsite = function(id) { $location.path('/websites/edit/' + id); }; }]);Esta es la directiva:
app.directive('wdaWebsitesOverview', function() { return { restrict: 'E', scope: { heading: '=', websites: '=', editWebsite: '&' }, templateUrl: 'views/websites-overview.html' } });Así es como se aplica la directiva en la plantilla principal:
<wda-websites-overview heading="'All websites'" websites="websites" edit-website="editWebsite(id)"></wda-websites-overview>y este método se llama desde la plantilla de directiva (website-overview.html):
<td data-ng-click="editWebsite(website.id)">EDIT</td>PREGUNTA: Cuando se hace clic en EDITAR, aparece este error en la consola:
TypeError: no se puede usar el operador 'in' para buscar 'editWebsite' en 1
¿Alguien sabe lo que pasa aquí?
Dado que definió un enlace de expresión ( & ), debe llamarlo explícitamente con un parámetro de objeto literal que contenga id si desea vincularlo en el HTML como edit-website="editWebsite(id)" .
De hecho, Angular necesita comprender cuál es esta id en su HTML, y dado que no es parte de su alcance, debe agregar lo que se llama "locales" a su llamada haciendo:
data-ng-click="editWebsite({id: website.id})"O como alternativa:
data-ng-click="onClick(website.id)"Con el controlador/código de enlace:
$scope.onClick = function(id) { // Ad "id" to the locals of "editWebsite" $scope.editWebsite({id: id}); } AngularJS incluye una explicación de esto en su documentación; busque el ejemplo que involucra "close({message: 'closing for now'})" en la siguiente URL:
TL;RD; - Está asumiendo que la función enlazada se pasa al componente secundario, como lo sería en React. Esto es incorrecto. De hecho, AngularJS está analizando la plantilla de cadena y creando una nueva función, que luego llama a la función principal.
Esta función generada espera recibir un objeto con claves y valores, en lugar de una simple variable.
Esto sucede cuando ha vinculado una función usando '&' y ha intentado llamar a esa función desde su controlador, pasando una variable simple en lugar de un objeto que contiene el nombre de la variable simple. El motor de plantillas necesita las claves de objeto para averiguar cómo pasar valores a la función enlazada.
p.ej. has llamado boundFunction('cats') en lugar boundFunction({value: 'cats'})
Digamos que creo un componente como este:
const MyComponent = { bindings: { onSearch: '&' }, controller: controller };Esta función (en el padre) se ve así:
onSearch(value) { // do search }En mi plantilla principal, ahora puedo hacer esto:
<my-component on-search="onSearch(value)"></my-component>El enlace aquí se analizará a partir de la cadena. En realidad no estás pasando la función. AngularJS está creando una función para usted que llama a la función. El enlace creado en la plantilla puede contener muchas cosas además de la llamada a la función.
AngularJS de alguna manera necesita averiguar de dónde obtener value , y lo hace al recibir un objeto del padre.
En el controlador myComponent, necesito hacer algo como:
handleOnSearch(value) { if (this.onSearch) { this.onSearch({value: value}) } }