Привязка метода элемента директивы AngularJS - 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>

и этот метод вызывается из шаблона директивы (website-overview.html):

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

ВОПРОС: При нажатии EDIT в консоли появляется эта ошибка:

TypeError: нельзя использовать оператор "in" для поиска "editWebsite" в 1

Кто-нибудь знает, что здесь происходит?

CodeVirtuoso
источник

Ответы:

180

Поскольку вы определили выражение binding ( &), вам необходимо явно вызвать его с параметром литерала объекта, содержащим, 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
Спасибо за ваш ответ и за указание точного местоположения в документации, это было невероятно полезно!
Бруно Белотти,
1
@floribon Я знаю, что это немного устарело, но есть ли у вас пример машинописного кодирования обратного вызова?
tcrite
Это действительно полезно, спасибо.
Anurag pareek
по-прежнему полезно для людей, работающих над устаревшими проектами .. спасибо
BMWCMW
" Часто желательно передавать данные из изолированной области через выражение в родительскую область; это можно сделать, передав карту имен и значений локальных переменных в функцию-оболочку выражения . Например, hideDialogфункция принимает сообщение для отображения, когда диалог скрыт. Это указывается в директиве путем вызова close({message: 'closing for now'}). Тогда локальная переменная messageбудет доступна в on-closeвыражении. "[emph mine] Истина страннее вымысла. Хотелось бы знать, как они выбрали это как лучшее решение для обработчиков событий.
Руффин
7

TL; DR; - Вы предполагаете, что связанная функция передается дочернему компоненту. Это неверно. Фактически, AngularJS анализирует шаблон строки и создает новую функцию, которая затем вызывает родительскую функцию.

Эта функция должна получать объект с ключами и значениями, а не простую переменную.

Более длинное объяснение

Это происходит, когда вы связали функцию с помощью '&' и попытались вызвать эту функцию из своего контроллера, передав простую переменную, а не объект, содержащий имя простой переменной. Ключи объекта необходимы шаблонизатору, чтобы решить, как передавать значения в связанную функцию.

например. ты позвонил, 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
Абсолютный денежный шар; спасибо: « вы boundFunction('cats')скорее позвонили , чемboundFunction({value: 'cats'}) »
ругань