속성에 지정된 angularjs 지시문 호출 함수 및 인수 전달


102

속성에 연결되는 지시문을 만들고 싶습니다. 속성은 범위에서 호출해야하는 함수를 지정합니다. 그러나 링크 함수 내에서 결정되는 함수에 인수를 전달하고 싶습니다.

<div my-method='theMethodToBeCalled'></div>

링크 함수에서 함수에 전달해야하는 인수를 전달하는 jQuery 이벤트에 바인딩합니다.

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.$apply(function() {expressionHandler(id);});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

ID를 전달하지 않고도 작동하도록 할 수 있지만 인수를 전달하려고하면 더 이상 함수가 호출되지 않습니다.


양방향 바인딩없이 격리 범위를 통해 개체 속성에 액세스하는 방법은 무엇입니까? 도움이된다고 생각합니다. 격리 된 범위를 사용하고 $ scope. $ parent를
— JJbang

답변:


98

Marko의 솔루션이 잘 작동합니다. .

권장되는 Angular 방식 (treeface의 plunkr에 표시됨)과 대조적으로 expressionHandler를 정의 할 필요가없는 콜백 표현식을 사용하는 것입니다. marko의 예제 변경에서 :

템플릿에서

<div my-method="theMethodToBeCalled(myParam)"></div>

지시 링크 기능에서

$(element).click(function( e, rowid ) {
  scope.method({myParam: id});
});

이것은 marko의 솔루션에 비해 한 가지 단점이 있습니다. 처음로드 할 때 theMethodToBeCalled 함수는 myParam === undefined로 호출됩니다.

작동하는 시험은 @treeface Plunker 에서 찾을 수 있습니다.


실제로 사용자 정의 속성에서 매개 변수와 함께 함수 이름을 제공하는이 패턴은 지시문에서 "콜백 함수"를 정의하는 가장 쉽고 강력한 방법 인 것 같습니다 ... thx !!
— rekna

3
속성과 범위 함수라는 두 가지 다른 것을 "setProduct"라고 부르는 것은 매우 혼란 스럽기 때문에 어느 것이 어디에 있는지 이해하기가 정말 어렵습니다.
— Dmitri Zaitsev

혼란스러운 것은 정답이 격리 범위를 사용하고 있지만 질문은 그렇지 않은 이유입니다. 아니면 내가 뭔가를 놓치고 있습니까?
— j_walker_dev 2014 년

이 코드를 각도 1.2.28로 사용한 테스트에서 잘 작동합니다. 내 테스트는 첫 번째로드에서 undefined로 theMethodToBeCalled를 호출하지 않습니다. 플 런커 예제도 마찬가지입니다. 이것은 문제가되지 않는 것 같습니다. 즉, 매개 변수를 지시문 링크 (격리 범위에서)로 전달하려는 경우 올바른 접근 방식으로 보입니다. 단점과 myParam === undefined에 관한 주석을 업데이트하는 것이 좋습니다.
— jazeee

이 "이것은 marko의 솔루션에 비해 한 가지 단점이 있습니다-처음로드 할 때 theMethodToBeCalled 함수가 myParam === undefined와 함께 호출됩니다"는 내 경우에 발생하지 않습니다 .... 여기에 암시 적 컨텍스트가있는 것 같습니다
— Victor

95

다른 답변에 정보를 추가하려면-사용 & 격리 된 범위가 필요한 경우 하는 것이 좋습니다.

marko 솔루션의 주된 단점은 요소에 대해 격리 된 범위를 만들도록 강요한다는 것입니다. 그러나 요소에는 그중 하나만있을 수 있습니다 (그렇지 않으면 각도 오류가 발생합니다. 여러 지시문 [지시문 1, 지시문 2] 격리 된 범위 용 )

이것은 당신을 의미합니다 :

  • 요소 모자에는 사용할 수 없습니다.
  • 동일한 요소에서이 솔루션과 함께 두 개의 지시문을 사용할 수 없습니다.

원래 질문은 restrict:'A'두 가지 상황 모두 에서 지시문을 사용하기 때문에 더 큰 응용 프로그램에서 자주 발생할 수 있으며 여기서 격리 된 범위를 사용하는 것은 좋은 관행이 아니며 불필요합니다. 실제로 rekna는이 경우에 좋은 직관을 가졌고 거의 작동했습니다. 그가 잘못한 유일한 일은 $ parsed 함수를 잘못 호출하는 것뿐입니다 (여기에서 반환되는 내용 참조 : https://docs.angularjs.org/api/ ng / service / $ parse ).

TL; DR; 고정 질문 코드

<div my-method='theMethodToBeCalled(id)'></div>

및 코드

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     // here you can parse any attribute (so this could as well be,
     // myDirectiveCallback or multiple ones if you need them )
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        calculatedId = // some function called to determine id based on rowid

        // HERE: call the parsed function correctly (with scope AND params object)
        expressionHandler(scope, {id:calculatedId});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

11
+1 실제로-스코프를 분리 할 필요가 없습니다. 훨씬 더 깨끗합니다!
— Dmitri Zaitsev

속성에 <div my-method = 'theMethodToBeCalled'> </ div>와 같은 메서드 이름 만 포함되거나 <div my-method = 'alert ( "hi");'> </ div>와 같은 인라인 함수가 포함 된 경우
— 조나단.

1
이러한 접근 방식 중 하나에 문제가있는 경우에서 반환 된 함수에 전달하는 범위에서 호출되는 메서드를 사용할 수 있어야합니다 $parse.
— ragamufin

이 대답은 정확히 내가 찾고 있던 것입니다. +1
— grimmdude

"theEvent"는 무엇입니까? 자식 div에서 함수를 어떻게 실행할 수 있습니까?
— Shlomo

88

원하는 작업을 정확히 알지 못하지만 여전히 가능한 해결책이 있습니다.

로컬 범위에서 '&'속성을 사용하여 범위를 만듭니다. "부모 범위의 컨텍스트에서 표현식을 실행하는 방법을 제공합니다"(자세한 내용은 지시문 문서 참조).

또한 속기 연결 기능을 사용하고 거기에 객체 속성을 넣었다는 것을 알았습니다. 당신은 그렇게 할 수 없습니다. 지시문 정의 객체를 반환하는 것이 더 명확합니다 (imho). 아래 내 코드를 참조하십시오.

여기에 코드 샘플과 바이올린이 있습니다.

<div ng-app="myApp">
<div ng-controller="myController">
    <div my-method='theMethodToBeCalled'>Click me</div>
</div>
</div>

<script>

   var app = angular.module('myApp',[]);

   app.directive("myMethod",function($parse) {
       var directiveDefinitionObject = {
         restrict: 'A',
         scope: { method:'&myMethod' },
         link: function(scope,element,attrs) {
            var expressionHandler = scope.method();
            var id = "123";

            $(element).click(function( e, rowid ) {
               expressionHandler(id);
            });
         }
       };
       return directiveDefinitionObject;
   });

   app.controller("myController",function($scope) {
      $scope.theMethodToBeCalled = function(id) { 
          alert(id); 
      };
   });

</script>

이 함수가 호출되면 theMethodToBeCalled 내에서 $ scope.id = id를 설정하면 뷰가 업데이트되지 않습니다. 아마도 scope.apply 안에 expressionHandler (id)를 래핑해야 할 것입니다.
— rekna

2
이것은 내 문제에 대한 해결책을 찾는 데 도움이되었습니다. 더 깊은 디렉티브 중첩을 수행하는 경우 최상위 수준에서만이 작업을 수행하면된다는 점을 언급 할 가치가 있습니다. 이것을 고려하십시오 : plnkr.co/edit/s3y67iGL12F2hDER2RNl?p=preview 여기서 두 개의 지시문을 통해 메소드를 전달합니다.
— treeface

3
그리고 여기에 두 번째 (아마 더 각진) 방법이 있습니다. plnkr.co/edit/r9CV9Y1RWRuse4RwFPka?p=preview
— treeface

1
스코프 격리없이 어떻게 할 수 있습니까?
— Evan Lévesque

3
+1이 솔루션은 내가 scope.method (); 먼저 메서드에 대한 실제 참조를 가져옵니다.
— Sal

6

를 사용 attrName: "&"하여 외부 범위의 식을 참조 하여 매개 변수로 함수 호출을 실행하는 지시문을 만들 수 있습니다 .

ng-click지시문을 ng-click-x다음 과 같이 바꾸고 싶습니다 .

<button ng-click-x="add(a,b)">Add</button>

이 범위가 있다면 :

$scope.a = 2;
$scope.b = 2;

$scope.add = function (a, b) {
  $scope.result = parseFloat(a) + parseFloat(b);
}

다음과 같이 지시문을 작성할 수 있습니다.

angular.module("ng-click-x", [])

.directive('ngClickX', [function () {

  return {

    scope: {

      // Reference the outer scope
      fn: "&ngClickX",

    },

    restrict: "A",

    link: function(scope, elem) {

      function callFn () {
        scope.$apply(scope.fn());
      }

      elem[0].addEventListener('click', callFn);
    }
  };
}]);

다음은 라이브 데모입니다. http://plnkr.co/edit/4QOGLD?p=info


2

여기에 저에게 효과적이었습니다.

지시문을 사용하는 HTML

 <tr orderitemdirective remove="vm.removeOrderItem(orderItem)" order-item="orderitem"></tr>

지시문의 HTML : orderitem.directive.html

<md-button type="submit" ng-click="remove({orderItem:orderItem})">
       (...)
</md-button>

지침의 범위 :

scope: {
    orderItem: '=',
    remove: "&",

0

내 솔루션 :

  1. 중합체에 이벤트를 발생 (예. complete)
  2. 이벤트를 제어 기능에 연결하는 지시문 정의

지령

/*global define */
define(['angular', './my-module'], function(angular, directives) {
    'use strict';
    directives.directive('polimerBinding', ['$compile', function($compile) {

            return {
                 restrict: 'A',
                scope: { 
                    method:'&polimerBinding'
                },
                link : function(scope, element, attrs) {
                    var el = element[0];
                    var expressionHandler = scope.method();
                    var siemEvent = attrs['polimerEvent'];
                    if (!siemEvent) {
                        siemEvent = 'complete';
                    }
                    el.addEventListener(siemEvent, function (e, options) {
                        expressionHandler(e.detail);
                    })
                }
            };
        }]);
});

폴리머 성분

<dom-module id="search">

<template>
<h3>Search</h3>
<div class="input-group">

    <textarea placeholder="search by expression (eg. temperature>100)"
        rows="10" cols="100" value="{{text::input}}"></textarea>
    <p>
        <button id="button" class="btn input-group__addon">Search</button>
    </p>
</div>
</template>

 <script>
  Polymer({
    is: 'search',
            properties: {
      text: {
        type: String,
        notify: true
      },

    },
    regularSearch: function(e) {
      console.log(this.range);
      this.fire('complete', {'text': this.text});
    },
    listeners: {
        'button.click': 'regularSearch',
    }
  });
</script>

</dom-module>

페이지

 <search id="search" polimer-binding="searchData"
 siem-event="complete" range="{{range}}"></siem-search>

searchData 제어 기능입니다

$scope.searchData = function(searchObject) {
                    alert('searchData '+ searchObject.text + ' ' + searchObject.range);

}

-2

작동합니다.

<div my-method='theMethodToBeCalled'></div>

app.directive("myMethod",function($parse) {
  restrict:'A',
  scope: {theMethodToBeCalled: "="}
  link:function(scope,element,attrs) {
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.theMethodToBeCalled(id);
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.