programing

템플릿에서 ngTransclus 지시어를 잘못 사용했습니다.

elecom 2023. 9. 25. 22:15
반응형

템플릿에서 ngTransclus 지시어를 잘못 사용했습니다.

두가지 지시사항이 있습니다.

app.directive('panel1', function ($compile) {
    return {
        restrict: "E",
        transclude: 'element',
        compile: function (element, attr, linker) {
            return function (scope, element, attr) {
                var parent = element.parent();
                linker(scope, function (clone) {
                    parent.prepend($compile( clone.children()[0])(scope));//cause error.
                  //  parent.prepend(clone);// This line remove the error but i want to access the children in my real app.
                });
            };
        }
    }
});

app.directive('panel', function ($compile) {
    return {
        restrict: "E",
        replace: true,
        transclude: true,
        template: "<div ng-transclude ></div>",
        link: function (scope, elem, attrs) {
        }
    }
});

제 견해는 이렇습니다.

<panel1>
    <panel>
        <input type="text" ng-model="firstName" />
    </panel>
</panel1>

오류: [ngTransclude:orphan] 템플릿에서 ngTransclude 지시문을 불법으로 사용했습니다!트랜스클루전이 필요한 상위 지시문을 찾을 수 없습니다.소:<div class="ng-scope" ng-transclude="">

패널 1이 실질적인 지침이 아니라는 것을 알고 있습니다.하지만 실제 애플리케이션에서도 이 문제가 발생합니다.

http://docs.angularjs.org/error/ngTransclude:orphan 에서 약간의 설명을 봅니다.그런데 여기에 왜 이런 오류가 발생하고 어떻게 해결해야 할지 모르겠습니다.

편집 저는 jsfiddle 페이지를 만들었습니다.미리 감사드립니다.

편집

In my real app panel1 does something like this:

    <panel1>
    <input type="text>
    <input type="text>
<!--other elements or directive-->
    </panel1>

결과 =>

    <div>
    <div class="x"><input type="text></div>
    <div class="x"><input type="text></div>
<!--other elements or directive wrapped in div -->
    </div>

그 이유는 DOM 로드가 완료되면 컴파일 및 링크 함수를 호출하기 에 각도가 DOM을 통과하여 모든 방향을 템플릿으로 변환하기 때문입니다.

를 할 때.$compile(clone.children()[0])(scope),clone.children()[0]s인.<panel>이 경우에는 이미 각도로 변환됩니다.clone.children()다가 .

<div ng-transclude="">fsafsafasdf</div>

(패널 요소를 제거하고 교체했습니다.)

입니다로 것도 ng-transclude인 div를 때.ng-transclude:,angular throws .

이 오류는 일부 지시어 정의에서 true를 설정한 다음 지시어 템플릿에서 ngTransclus를 사용하는 것을 잊어버린 경우에 종종 발생합니다.

DEMO(출력을 보려면 콘솔을 확인합니다)

도.replace:false당신의 것을 유지하다<panel> 될 , 입니다.

<panel class="ng-scope"><div ng-transclude=""><div ng-transclude="" class="ng-scope"><div ng-transclude="" class="ng-scope">fsafsafasdf</div></div></div></panel>

ng-transclude됩니다.

데모

각도 컴파일 프로세스충돌하지 않으려면 내부 html을 설정하는 것이 좋습니다.<panel1>릿Url

HTML:

<div data-ng-app="app">
        <panel1>

        </panel1>
    </div>

JS:

app.directive('panel1', function ($compile) {
            return {
                restrict: "E",
                template:"<panel><input type='text' ng-model='firstName'>{{firstName}}</panel>",

            }
        });

보시다시피 이 코드는 수동으로 요소를 제거할 필요가 없기 때문에 더 깨끗합니다.

데모

템플릿이나 템플릿을 사용하지 않고 동적으로 요소를 추가할 수 있는 솔루션으로 업데이트Url:

app.directive('panel1', function ($compile) {
            return {
                restrict: "E",
                template:"<div></div>",
                link : function(scope,element){
                    var html = "<panel><input type='text' ng-model='firstName'>{{firstName}}</panel>";
                    element.append(html);
                    $compile(element.contents())(scope);
                }
            }
        });

데모

html 페이지에 넣으려면 다시 컴파일하지 마십시오.

데모

만약 당신이 각 아이들에게 디파퍼를 추가해야 한다면. 밖의를 사용하세요.ng-transclude.

app.directive('panel1', function ($compile) {
            return {
                restrict: "E",
                replace:true,
                transclude: true,
                template:"<div><div ng-transclude></div></div>" //you could adjust your template to add more nesting divs or remove 
            }
        });

데모(템플릿을 필요에 맞게 조정하거나, 디브를 제거하거나, 디브를 추가해야 할 수도 있습니다.

OP의 업데이트된 질문에 기반한 솔루션:

app.directive('panel1', function ($compile) {
            return {
                restrict: "E",
                replace:true,
                transclude: true,
                template:"<div ng-transclude></div>",
                link: function (scope, elem, attrs) {
                    elem.children().wrap("<div>"); //Don't need to use compile here.
                   //Just wrap the children in a div, you could adjust this logic to add class to div depending on your children
                }
            }
        });

데모

당신은 당신의 코드에서 몇 가지 잘못을 하고 있습니다.목록을 만들어 보겠습니다.

첫째로, 각 1.2.6을 사용하고 있으므로 컴파일 함수에 대한 매개 변수로 트랜스클루전(당신의 링커 함수)을 더 이상 사용해서는 안 됩니다.이는 사용되지 않았으며 이제 링크 함수의 5번째 매개 변수로 전달되어야 합니다.

compile: function (element, attr) {
  return function (scope, element, attr, ctrl, linker) {
  ....};

이것이 현재 보고 있는 특정 문제를 야기하는 것은 아니지만, 사용하지 않는 구문 사용을 중지하는 것이 좋습니다.

는 적용하느냐에 .panel1지시:

parent.prepend($compile(clone.children()[0])(scope));

무엇이 잘못된 것인지에 대해 살펴보기 전에, 어떻게 트랜스클루전이 작동하는지 빨리 살펴보도록 하겠습니다.

명령어가 트랜스클루전을 사용할 때마다 제외된 내용은 돔에서 제거됩니다.그러나 컴파일된 내용은 링크 함수의 5번째 파라미터(통칭 트랜스클루드 함수)로 전달된 함수를 통해 접근할 수 있습니다.

핵심은 내용이 정리된 것입니다.이것은 당신이 당신의 제외물에 전달된 도메인에서 $compile을 호출하지 말아야 한다는 것을 의미합니다.

또한 제외된 DOM을 삽입하려고 할 때 부모에게 가서 거기에 추가하려고 합니다.일반적으로 지시자는 자신의 도메인 조작을 자신의 요소 이하로 제한하고 부모 도메인을 수정하려고 해서는 안 됩니다.이것은 DOM을 순서대로 계층적으로 횡단하는 각도를 크게 혼동할 수 있습니다.

봤을 때,하기 위한 더 방법은 , 를 입니다.transclude: truetransclude: 'element' 차이점을 설명해 보겠습니다.

transclude: 'element'요소 자체를 DOM에서 제거하고 트랜스클루드 함수를 호출하면 전체 요소를 반환합니다.

transclude: true원소의 아이들을 왕국에서 제거하고, 당신이 당신의 제외자를 부를 때 당신에게 아이들을 돌려줄 것입니다.

자식만 관심이 있는 것 같으니 클론에서 자식을 가져오는 대신 transclude true를 사용해야 합니다.그러면 단순히 요소를 해당 요소의 자식으로 대체할 수 있습니다(따라서 올라가 부모를 괴롭히지 않음).

마지막으로, 제외된 기능의 범위를 무시하는 것은 적절한 이유가 없는 한 좋지 않습니다(일반적으로 제외된 내용은 원래 범위를 유지해야 함). 당신이 때 입니다.linker().

최종적으로 간소화된 지침은 다음과 같습니다.

   app.directive('panel1', function ($compile) {
     return {
       restrict: "E",
       transclude: true,
       link: function (scope, element, attr, ctrl, linker) {
           linker(function (clone) {
               element.replaceWith(clone);
           });
       }
    }
   });

에 대한 이전 답변에서 언급된 내용을 무시합니다.replace: true그리고.transclude: true. 그것은 일이 그렇게 작동하는 방식이 아니며 패널 지침은 괜찮으며 당신이 당신의 것을 고치는 한 기대한 만큼 작동해야 합니다.panel1지시의

여기 제가 수정한 js-fiddle이 있습니다. 당신이 기대하는 대로 효과가 있기를 바랍니다.

http://jsfiddle.net/77Spt/3/

편집:

제외된 내용을 디브로 포장할 수 있는지 물었습니다.가장 쉬운 방법은 다른 지시문처럼 단순히 템플릿을 사용하는 것입니다(템플릿의 id는 HTML에서 볼 수 있도록 하기 위한 것일 뿐, 다른 목적에는 도움이 되지 않습니다).

   app.directive('panel1', function ($compile) {
       return {
           restrict: "E",
           transclude: true,
           replace: true,
           template: "<div id='wrappingDiv' ng-transclude></div>"          
       }
   });

또는 transclude 함수(나의 개인 취향)를 사용하려면:

   app.directive('panel1', function ($compile) {
       return {
           restrict: "E",
           transclude: true,
           replace: true,
           template: "<div id='wrappingDiv'></div>",
           link: function (scope, element, attr, ctrl, linker) {
               linker(function (clone) {
                   element.append(clone);
               });
           }
       }
   });

제가 이 구문을 선호하는 이유는ng-transclude쉽게 혼동되는 단순하고 바보 같은 지시입니다.이런 상황에서는 간단하지만 원하는 위치에 돔을 수동으로 추가하는 것이 안전한 방법입니다.

이것이 그것을 위한 바이올린입니다.

http://jsfiddle.net/77Spt/6/

이것은 내가 가지고 있었기 때문에.directiveChild에 둥지를 튼directiveParent의 결과로transclude.

비결은 바로directiveChild실수로 같은 걸 사용하고 있었습니다.templateUrl~하듯이directiveParent.

언급URL : https://stackoverflow.com/questions/20718127/illegal-use-of-ngtransclude-directive-in-the-template

반응형