AngularJS指令元素方法绑定 - TypeError:不能使用'in'运算符来搜索1中的'functionName'

Cod*_*oso 85 javascript angularjs angularjs-directive angularjs-scope

这是主模板的控制器:

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

这是指令:

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

这是指令在主模板中的应用方式:

<wda-websites-overview heading="'All websites'" websites="websites" edit-website="editWebsite(id)"></wda-websites-overview>
Run Code Online (Sandbox Code Playgroud)

这是从指令模板(website-overview.html)调用的方法:

<td data-ng-click="editWebsite(website.id)">EDIT</td>
Run Code Online (Sandbox Code Playgroud)

问题:单击EDIT时,控制台中会出现此错误:

TypeError:无法使用"in"运算符在1中搜索"editWebsite"

有谁知道这里发生了什么?

flo*_*bon 173

由于您定义了一个表达式binding(&),因此您需要使用包含idif,如果要在HTML中将其绑定的JSON明确地调用它edit-website="editWebsite(id)".

实际上,Angular需要了解idHTML中的内容,并且由于它不属于您的范围,因此您需要通过执行以下操作向调用添加所谓的"本地":

data-ng-click="editWebsite({id: website.id})"
Run Code Online (Sandbox Code Playgroud)

或作为替代方案:

data-ng-click="onClick(website.id)"
Run Code Online (Sandbox Code Playgroud)

使用控制器/链接代码:

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

这在此处记录,查找涉及的示例 "close({message: 'closing for now'})"

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

  • 感谢您的回答,并指出文档中的准确位置,这是令人难以置信的有用! (7认同)

sup*_*ary 8

TL; 博士;- 您假设绑定函数正在传递给子组件,就像在 React 中一样。这是不正确的。事实上,AngularJS 正在解析字符串模板并创建一个新函数,然后调用父函数。

这个生成的函数期望接收一个带有键和值的对象,而不是一个普通的变量。

更长的解释

当您使用“&”绑定一个函数,并尝试从控制器调用该函数,传递一个普通变量而不是包含普通变量名称的对象时,就会发生这种情况。模板引擎需要对象键来确定如何将值传递给绑定函数。

例如。你打电话boundFunction('cats')而不是boundFunction({value: 'cats'})

工作示例

假设我创建了一个这样的组件:

const MyComponent = {
  bindings: {
    onSearch: '&'
  },
  controller: controller
};
Run Code Online (Sandbox Code Playgroud)

这个函数(在父函数中)看起来像这样:

onSearch(value) {
  // do search
}
Run Code Online (Sandbox Code Playgroud)

在我的父模板中,我现在可以这样做:

<my-component on-search="onSearch(value)"></my-component>
Run Code Online (Sandbox Code Playgroud)

这里的绑定将从字符串中解析出来。你实际上并没有传递函数。AngularJS 正在为您制作一个调用该函数的函数。在模板中创建的绑定可以包含除函数调用之外的许多内容。

AngularJS 以某种方式需要确定从哪里获取value,它通过从父级接收对象来实现这一点。

在 myComponent 控制器中,我需要执行以下操作:

handleOnSearch(value) {
  if (this.onSearch) {
    this.onSearch({value: value})
  }
}
Run Code Online (Sandbox Code Playgroud)