속성에 지정된 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.