AngularJS: ngIf를 명령어에 프로그래밍 방식으로 추가하는 베스트 프랙티스는 무엇입니까?
서비스에서 가져온 값을 기준으로 요소가 돔에 존재해야 하는지 여부를 확인하는 지시문을 만들고 싶습니다(예: 사용자 역할 확인).
대응하는 디렉티브는 다음과 같습니다.
angular.module('app', []).directive('addCondition', function($rootScope) {
return {
restrict: 'A',
compile: function (element, attr) {
var ngIf = attr.ngIf,
value = $rootScope.$eval(attr.addCondition);
/**
* Make sure to combine with existing ngIf!
* I want to modify the expression to be evalued by ngIf here based on a role
* check for example
*/
if (ngIf) {
value += ' && ' + ngIf;
}
attr.$set('ng-if', value);
}
};
});
마지막 요소에는 ng-if 속성이 부가되어 있지만 어떤 이유에서인지 요소에는 적용되지 않고 돔에 존재합니다.그래서 이것은 명백히 잘못된 접근법이다.
이 바이올린은 문제를 나타내고 있습니다.http://jsfiddle.net/L37tZ/2/
왜 이런 일이 일어나는지 누가 설명할 수 있을까요?유사한 행동을 할 수 있는 다른 방법이 있습니까?기존 ngIfs를 고려해야 합니다.
해결책:
사용방법:<div rln-require-roles="['ADMIN', 'USER']">I'm hidden when theses role requirements are not satifisfied!</div>
.directive('rlnRequireRoles', function ($animate, Session) {
return {
transclude: 'element',
priority: 600,
terminal: true,
restrict: 'A',
link: function ($scope, $element, $attr, ctrl, $transclude) {
var block, childScope, roles;
$attr.$observe('rlnRequireRoles', function (value) {
roles = $scope.$eval(value);
if (Session.hasRoles(roles)) {
if (!childScope) {
childScope = $scope.$new();
$transclude(childScope, function (clone) {
block = {
startNode: clone[0],
endNode: clone[clone.length++] = document.createComment(' end rlnRequireRoles: ' + $attr.rlnRequireRoles + ' ')
};
$animate.enter(clone, $element.parent(), $element);
});
}
} else {
if (childScope) {
childScope.$destroy();
childScope = null;
}
if (block) {
$animate.leave(getBlockElements(block));
block = null;
}
}
});
}
};
});
지시문에 우선순위를 추가하는 것이 매우 중요합니다. 그렇지 않으면 해당 요소에 첨부된 다른 지시문은 평가되지 않습니다.
재사용 가능ngIf
다음과 같이 지시합니다.
/** @const */ var NAME = 'yourCustomIf';
yourApp.directive(NAME, function(ngIfDirective) {
var ngIf = ngIfDirective[0];
return {
transclude: ngIf.transclude,
priority: ngIf.priority,
terminal: ngIf.terminal,
restrict: ngIf.restrict,
link: function($scope, $element, $attr) {
var value = $attr[NAME];
var yourCustomValue = $scope.$eval(value);
$attr.ngIf = function() {
return yourCustomValue;
};
ngIf.link.apply(ngIf, arguments);
}
};
});
이렇게 해서
<div your-custom-if="true">This is shown</div>
그리고 그것은 모든 "유동성"을 사용할 것이다.ngIf
.
Joscha의 답변은 꽤 괜찮지만, ng-if를 추가로 사용한다면 이 방법은 효과가 없을 것입니다.Joscha의 코드를 가져와 기존 ng-if 디렉티브와 결합하기 위해 몇 줄 추가했습니다.
angular.module('myModule').directive('ifAuthenticated', ['ngIfDirective', 'User', function(ngIfDirective, User) {
var ngIf = ngIfDirective[0];
return {
transclude: ngIf.transclude,
priority: ngIf.priority - 1,
terminal: ngIf.terminal,
restrict: ngIf.restrict,
link: function(scope, element, attributes) {
// find the initial ng-if attribute
var initialNgIf = attributes.ngIf, ifEvaluator;
// if it exists, evaluates ngIf && ifAuthenticated
if (initialNgIf) {
ifEvaluator = function () {
return scope.$eval(initialNgIf) && User.isAuthenticated();
}
} else { // if there's no ng-if, process normally
ifEvaluator = function () {
return User.isAuthenticated();
}
}
attributes.ngIf = ifEvaluator;
ngIf.link.apply(ngIf, arguments);
}
};
}]);
그럼 다음과 같은 작업을 수행할 수 있습니다.
<input type="text" ng-model="test">
<div ng-if="test.length > 0" if-authenticated>Conditional div</div>
그리고 그 조건들은div
인증이 완료되어 테스트 입력이 비어 있지 않은 경우에만 표시됩니다.
당신의 질문의 첫 번째 부분인 "왜?"는 제가 대답할 수 있는 부분입니다.
호출하지 않고서는 디렉티브를 요소에 동적으로 적용할 수 없다는 문제가 있습니다.$compile
비바람을 쐬다.
전화하시면$compile(element)(element.scope())
Atribute 설정 후, 자신을 컴파일 하고 있기 때문에 스택 오버플로우가 발생하고, 이로 인해 자신을 컴파일 하는 등의 원인이 됩니다.
두 번째는 '어떻게 하면 달성할 수 있을까'입니다.몇 가지 방법을 시도했습니다(내스트된 내용으로 내용을 변환하는 등).ng-if
하지만 당신이 원하는 행동을 정확히 이해할 수 없습니다.
다음 단계는 ng-if의 코드를 연구하여 당신의 지시문에 직접 비슷한 것을 구현해 보는 것이 좋을 것 같습니다.
여기 그것을 작동시키기 위한 첫 번째 패스입니다.하지만 정말 원하는 대로 작동하려면 약간의 청소와 수정이 필요할 것 같습니다.
템플릿 기능을 사용하여 이 문제를 해결하는 다른 방법이 있습니다.이렇게 하려면 jquery 1.6+가 필요합니다.
코드 조작: http://jsfiddle.net/w72P3/6/
return {
restrict: 'A',
replace: true,
template: function (element, attr) {
var ngIf = attr.ngIf;
var value = attr.addCondition;
/**
* Make sure to combine with existing ngIf!
*/
if (ngIf) {
value += ' && ' + ngIf;
}
var inner = element.get(0);
//we have to clear all the values because angular
//is going to merge the attrs collection
//back into the element after this function finishes
angular.forEach(inner.attributes, function(attr, key){
attr.value = '';
});
attr.$set('ng-if', value);
return inner.outerHTML;
}
}
합니다.replace: true는 내장요소를 방지합니다. 반환되는 은 htmlreplace=true에 저장됩니다. , html은 html로 반환됩니다.<a href="#" addCondition="'true'">Hello</a>
becomes가 되다<a href="#" ng-if="'true'"><a href="#" ng-if="'true'">Hello</a></a>
상세한 것에 대하여는, https://docs.angularjs.org/api/ng/service/$compile 를 참조해 주세요.
return {
restrict: 'A',
terminal: true,
priority: 50000, // high priority to compile this before directives of lower prio
compile: function compile(element, attrs) {
element.removeAttr("add-condition"); // avoid indefinite loop
element.removeAttr("data-add-condition");
return {
pre: function preLink(scope, iElement, iAttrs, controller) { },
post: function postLink(scope, iElement, iAttrs, controller) {
iElement[0].setAttribute('ng-if', iAttrs.addCondition);
$compile(iElement)(scope);
}
};
}
와 'priority'의terminal: true
기본은 다음과 같습니다.터미널 플래그는 Angular에게 동일한 HTML 요소에서 우선순위가 낮은 모든 지시어를 건너뛰도록 지시합니다.
는 이 때문에 .add-condition
ng-if
를 호출하기 compile
ng-if
기타 지시사항도 있습니다.
언급URL : https://stackoverflow.com/questions/20325480/angularjs-whats-the-best-practice-to-add-ngif-to-a-directive-programmatically
'source' 카테고리의 다른 글
타이프스크립트 오류:TS7053 요소에는 암묵적으로 '임의' 유형이 있습니다. (0) | 2023.03.13 |
---|---|
입력 타입="파일"에 이미지를 추가해 같은 형태로 송신한 후 섬네일 이미지를 생성하는 방법 (0) | 2023.03.13 |
Spring-Data JPA CrudRepository는 Itable을 반환합니다.목록에 캐스팅해도 될까요? (0) | 2023.03.13 |
Ajax 요청 시 Angularjs 로드 화면 (0) | 2023.03.13 |
ExtJS 철학이란?한 페이지 어플리케이션? (0) | 2023.03.13 |