web-dev-qa-db-ja.com

AngularJSディレクティブ要素メソッドバインディング-TypeError: 'in'演算子を使用して1の 'functionName'を検索することはできません

これはメインテンプレートのコントローラーです。

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>

質問:[編集]をクリックすると、コンソールに次のエラーが表示されます。

TypeError:「in」演算子を使用して「editWebsite」を検索することはできません1

誰がここで何が起こっているか知っていますか?

84
CodeVirtuoso

式バインディング(&)を定義したため、HTMLでedit-website="editWebsite(id)"としてバインドする場合は、idを含むJSONで明示的に呼び出す必要があります。

実際、Angularは、このidがHTMLに含まれていることを理解する必要があります。これはスコープの一部ではないため、「locals」と呼ばれるものを呼び出しに追加する必要があります。

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});
}

これはここに文書化されています。"close({message: 'closing for now'})"を含む例を探してください

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

171
floribon

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
superluminary