0

다음 시나리오에 대한 내 접근 방식에 어려움을 겪고 있습니다. 나는 사용자 정의 지시어 authorize을 가지고 그룹의 이름을 전달합니다. 현재 사용자가 프로파일에이 그룹이 있으면 요소가 표시되고 그렇지 않으면 요소가 숨겨집니다. 예 :가시성에 따라 작동하는 동일한 요소의 여러 지시문

<button class="btn btn-default" role="button" 
     ng-click="myVm.edit()" 
     authorize="{{myVm.groupName}}"><!--groupName = "accountants"--> 
    <span class="fa fa-edit" aria-hidden="true"></span> Edit 
</button> 

와이 제대로 작동

namespace app.blocks.directives { 
    "use strict"; 

    class AuthorizeDirective implements ng.IDirective { 

     public restrict: string = "A"; 

     public replace: boolean = true; 

     constructor(private $compile: ng.ICompileService, private authService: services.IAuthService) { 
     } 

     public static factory(): ng.IDirectiveFactory { 
      const directive = ($compile: ng.ICompileService, authService: services.IAuthService) => 
       new AuthorizeDirective($compile, authService); 
      directive.$inject = [ 
       "$compile", 
       "app.services.AuthService" 
      ]; 
      return directive; 
     } 

     public link(scope: ng.IScope, instanceElement: ng.IAugmentedJQuery, instanceAttributes: ng.IAttributes): void { 
      let groupName: string = (<any>instanceAttributes).authorize; 
      let element = angular.element(instanceElement); 
      let hasGroup: boolean = this.authService.hasGroup(groupName); 
      element.attr("ng-show", String(hasGroup)); 
      //remove the attribute, otherwise it creates an infinite loop. 
      element.removeAttr("authorize"); 
      this.$compile(element)(scope); 
      } 
     } 
    } 

    angular 
     .module("app.blocks.directives") 
     .directive("authorize", AuthorizeDirective.factory()); 
} 

버튼이 authService가 false를 반환하는 경우 숨겨진 링크 기능 (필자는 DOM에서 작동하기 때문에)를 사용하여 타이프 라이터 authorize.ts에서 내 원래 지침 사용자가 해당 그룹에 속하지 않으므로 (예 : "accountants")

내 DOM 요소에 ng-show 또는 ng-hide 지시문이있는 경우 문제가 발생합니다. 예 :

<button class="btn btn-default" role="button" 
     ng-hide="myVm.isDeleted" 
     ng-click="myVm.edit()" 
     authorize="{{myVm.groupName}}"> 
    <!--groupName = "accountants"--> 
    <span class="fa fa-edit" aria-hidden="true"></span> Edit 
</button> 

myVm.isDeleted = true (이것은 사용자가 내 authorize 지시에 따라 지정된 그룹에 속하지 않는 안하기 때문에 경우)가 표시됩니다 내 지침 및 DOM 요소의 결과를 무시하는 것 같다.

지시어에 우선 순위 (기본값은 0)가 있다는 것을 알고 있습니다. 두 지침의 우선 순위가 같을 경우 문서에 따라 사전 순으로 실행됩니다. This post은이를 이해하는 데 매우 도움이되었습니다.

그래서 여기에 몇 가지 옵션이 다음 NG-숨기기 요소가 표시되어야한다고 말한다면 있지만 :

  1. 내 권한 부여 지침 (즉 계산하기 위해 ng-hide 또는 ng-show의 조건을 평가 되세요 사용자가 특정 그룹을 가지고 있지 않다면, 그 요소는 숨겨 져야한다). 내 지시 링크의 기능에서 myVm.isDeleted에 액세스하는 방법을 찾지 못했습니다. 아무도 내가이 접근 방식에 만족할 줄 안다면.

  2. authorize 지시어는 다른 지시하기 전에 실행하고 나중에 ng-show 또는 ng-hide (에 따라 가시성을 결정하는 각도에 의존 적이 예 : 내 authorize 지시어는 사용자가에 속하지 않기 때문에 요소가 숨겨져되어야한다고 판단하는 경우 DOM 요소를 변환하고 DOM 요소를 변환해야합니다. 예를 들어 ng-show="false"을 각도로 표시하면 나중에 요소가 숨겨집니다.이 방법은 작동하지 않는 것 같습니다. DOM이 올바른 것 같습니다. 버튼이 표시됩니다. = "false"하지만 어떤 이유로 든 여전히 화면에있는 버튼을 보았습니다 그래서 Angular가 그 요소를 숨겨야한다는 것을 모르는 것처럼 보였습니다. 재미있는 점은 다른 탭으로 이동하면 되돌아갑니다 (보기가 다시로드되고 지시문이 다시 실행되는) 동일한 탭으로 이동하면 올바르게 작동합니다. 무슨 일 이니?.

나는 옵션 2로 가서이는 DOM을 조작 제대로 작동하는 것 같다 코드입니다,하지만 결과는 예상과 그에 각도가 나중에 NG 쇼 지침을 적용하지 않습니다.

public priority: number = 999; //High priority so it is executed BEFORE ng-show directive 

public link(scope: ng.IScope, instanceElement: ng.IAugmentedJQuery, instanceAttributes: ng.IAttributes): void { 
    let groupName: string = (<any>instanceAttributes).authorize; 
    let element = angular.element(instanceElement); 
    let ngShow: string = (<any>instanceAttributes).ngShow; 
    let ngHide: string = (<any>instanceAttributes).ngHide; 
    let hasGroup: boolean = this.authService.hasGroup(groupName); 
    let ngHideValue = ngHide ? "!" + ngHide : ""; 
    let ngShowValue = ngShow ? ngShow : ""; 
    //if hasGroup, use whatever ng-show or ng-hide value the element had (ng-show = !ng-hide). 
    //if !hasGroup, it does not matter what value the element had, it will be hidden. 
    if (hasGroup) { 
     element.attr("ng-show", (ngShowValue + ngHideValue) || "true"); 
    } else { 
     element.attr("ng-show", "false"); 
    } 
    element.removeAttr("ng-hide"); 
    //remove the attribute, otherwise it creates an infinite loop. 
    element.removeAttr("authorize"); 
    this.$compile(element)(scope); 
} 
+0

확실한 해결 방법은 내 버튼을 div에 넣고 div 자체에 'authorize' 지시문을 적용하고 버튼에 ng-hide를두고 버튼 자체에 여러 지시문이 충돌하지 않도록하는 것입니다. 하지만 내 질문에 대한 해결책을 찾고 angle이 왜 'ng-show = "false"를 다시 계산하지 않는지 이해하고 싶습니다. – iberodev

답변

2

내가 주장하는 것 당신의 authorize 지시어는 기본적으로 그냥 디스플레이를 배치하거나 아니라고 요소, 당신은 당신이 당신의 컨트롤러에 주입하는 서비스로 아웃의 논리를 이동하고 ng-hide을하도록해야할지 여부를 제어로보고 요소가 디자인 된 것처럼 표시할지 여부를 제어합니다.

이 이해하기 나중에 올 개발자를위한 쉬울 것 - 아무도 서버를 호출 코드의 다양한 흩어져 비트를 찾기 위해 각각의 지시로 드릴 다운을 가고 싶어하지 않으며, 당신의 버튼은 바로 다음과 같습니다

<button class="btn btn-default" role="button" 
    ng-hide="myVm.isDeleted || !myVm.isAuthorized(myVm.groupName)" 
    ng-click="myVm.edit()"> 
    <span class="fa fa-edit" aria-hidden="true"></span> Edit 
</button> 

멋지고 읽기 쉽습니다.

+0

'ng-hide' 또는'ng-show'에 의존하여 당신의 의견에 동의합니다. 서비스의 결과에 따라 그들이 아는 것 (숨기기 또는 표시 요소)이 더 좋고 더 읽기 쉬운 해결책으로 보이지만 지시문의'link' 함수에서 vm 속성에 액세스하거나 문제가 발생했을 때 각도 재 할당을 사용하여 문제를 해결하지 못합니다. 내 지시어가 끝난 후에 DOM을 계산한다. 우선 순위를 정해서 해결할 수 없다. :-) – iberodev

+0

DOM 사전 컴파일을 망치고 싶다면 다음과 같이하면된다. 링크 – s3raph86

+1

흠 ... 그런 다음 몇 가지 문제가 있습니다. 내가 볼 수있는 것만 큼 가까스로 VM웨어 하우스는 분리 된 범위가 없으므로 이미 볼 수 있어야합니다. 솔루션에서 DOM * 이전 *을 컴파일로 변경해야하는 경우 링크 함수에서 수행 할 수 없습니다. [각도 문서] (https : /)에 설명 된대로 '컴파일' /docs.angularjs.org/api/ng/service/$compile) – s3raph86