2016-10-04 3 views
3

문장 작성을위한 각도 지시문을 만들려고합니다. 목표는 목록을 가져 와서 필요한만큼 반복하는 것입니다.템플릿을 사용한 각도 1.x 지시문

신발, 바지와 양말

또는

신발, 바지 5 개

I : 지침의 결과는 다음과 같을 것이다 문자열 배열을 사용하도록 기본 지시문을 설정하십시오.하지만 사용자 정의 테를 허용하도록 사용자 정의하고 싶습니다. 각 문장 요소 (즉, 하이퍼 링크, 스타일링 등). 즉 : 나는 transclude 함께 할 수있는 뭔가가 추측하고있어하지만 API를 알아낼 수 없습니다

$scope.articles = [ 
    { title: '...', author: '...'}, 
    { title: '...', author: '...'}, 
    ... 
] 

<span><strong>ABC</strong> by <span>123</span></span> 
<span>, </span> 
<span><strong>DEF</strong> by <span>456</span></span> 
<span>and</span> 
<span>+5 more</span> 

: 사용자가 브라우저에서 볼 수

<sentence values="article in articles"> 
<strong>{{article.title}}</strong> by <span>{{article.author}}</span> 
</sentence> 

html로 뭔가 같이 할 필요가있다. 또한 지시문 템플릿 대신 ng-repeat을 사용하여 실험했지만 해결 방법을 찾을 수 없었습니다. 이 같은

+0

ng-repeat = "article in articles"을 사용하면 필요한 "문장"태그가 만들어집니다. –

+0

나는'ng-repeat'을 사용하여 모든 태그를 반복 할 수 있음을 알고 있습니다. 내 목표는 문장을 생성하는 것입니다 (즉, ","및 "와")는 문장이 3보다 길면 "+5 이상"을 표시합니다. 하나의 버전을 빌드하는 방법을 알고 있지만, 재사용이 가능한 지시문을 사용하여 앱의 여러 영역에서 사용할 수 있기를 원합니다. 또는 나는 무엇인가 놓치고 있냐? – Stussa

+0

당신이 찾고있는 것은 필터처럼 더 비슷합니다. – MilitelloVinx

답변

1

뭔가 maxArticles 동적 콘텐츠를 제공 을 반복하는 당신의 범위

<sentence values="article in articles | limitTo: maxArticles"> 
    <strong>{{article.title}}</strong> by <span>{{article.author}}</span> 
    <span ng-if="$index < maxArticles - 2">, </span> 
    <span ng-if="$index === articles.length - 1 && articles.length <= maxArticles">and</span> 
</sentence> 
<span ng-if="articles.length > maxArticles"> 
    and +{{articles.length - maxArticles}} more. 
</span> 
0

에 정의 된 번호가 compile 기능 +를 $compile 서비스 사용자 정의 지시어에 대한 일반적인 사용으로 어디 작동합니다. 조심해 : 본질적으로 당신은 ng-repeat의 기능을 되풀이하고 있습니다. 대안을 고려해보십시오.

예. articles 목록 대신 다른 이름 (아마도 articlesLimited)을 사용하십시오. 새 목록은 동적으로 생성되며 articles의 첫 번째 요소를 포함합니다. 플래그 (예 : hasMore)는 원본 articles에 더 많은 요소가 있는지 여부를 나타냅니다. 간단히 : $scope.hasMore = articles.length > 5입니다. hasMore 플래그를 사용하여 "+ N more"메시지를 표시하거나 숨 깁니다.

그러나 아래 내용은 sentence 지시문의 구현입니다. 약점에 대한 코멘트를보십시오!

app.directive('sentence', ['$compile', function($compile) { 
    var RE = /^([a-z_0-9\$]+)\s+in\s([a-z_0-9\$]+)$/i, ONLY_WHITESPACE = /^\s*$/; 

    function extractTrimmedContent(tElem) { 
    var result = tElem.contents(); 
    while(result[0].nodeType === 3 && ONLY_WHITESPACE.test(result[0].textContent)) { 
     result.splice(0, 1); 
    } 
    while(result[result.length-1].nodeType === 3 && ONLY_WHITESPACE.test(result[result.length-1].textContent)) { 
     result.length = result.length - 1; 
    } 
    return result; 
    } 

    function extractIterationMeta(tAttrs) { 
    var result = RE.exec(tAttrs.values); 
    if(!result) { 
     throw new Error('malformed values expression, use "itervar in list": ', tAttrs.values); 
    } 
    var cutoff = parseInt(tAttrs.cutoff || '5'); 
    if(isNaN(cutoff)) { 
     throw new Error('malformed cutoff: ' + tAttrs.cutoff); 
    } 
    return { 
     varName: result[1], 
     list: result[2], 
     cutoff: cutoff 
    }; 
    } 

    return { 
    scope: true, // investigate isolated scope too... 
    compile: function(tElem, tAttrs) { 
     var iterationMeta = extractIterationMeta(tAttrs); 

     var content = $compile(extractTrimmedContent(tElem)); 
     tElem.empty(); 

     return function link(scope, elem, attrs) { 
     var scopes = []; 
     scope.$watchCollection(
      function() { 
      // this is (IMO) the only legit usage of scope.$parent: 
      // evaluating an expression we know is meant to run in our parent 
      return scope.$parent.$eval(iterationMeta.list); 
      }, 
      function(newval, oldval) { 
      var i, item, childScope; 

      // this needs OPTIMIZING, the way ng-repeat does it (identities, track by); omitting for brevity 
      // if however the lists are not going to change, it is OK as it is 
      scopes.forEach(function(s) { 
       s.$destroy(); 
      }); 
      scopes.length = 0; 
      elem.empty(); 

      for(i=0; i < newval.length && i < iterationMeta.cutoff; i++) { 
       childScope = scope.$new(false, scope); 
       childScope[iterationMeta.varName] = newval[i]; 
       scopes.push(childScope); 
       content(childScope, function(clonedElement) { 
       if(i > 0) { 
        elem.append('<span class="sentence-sep">, </span>'); 
       } 
       elem.append(clonedElement); 
       }); 
      } 

      if(newval.length > iterationMeta.cutoff) { 
       // this too can be parametric, leaving for another time ;) 
       elem.append('<span class="sentence-more"> +' + (newval.length - iterationMeta.cutoff) + ' more</span>'); 
      } 
      } 
     ); 
     }; 
    } 
    }; 
}]); 

그리고 바이올린 : https://jsfiddle.net/aza6u64p/

0

이 까다로운 문제입니다. Transclude 요소를 포장하는 데 사용되지만 transclude를 사용할 때 당신은 단지 지시어가 사용되는 위치의 범위에,이 지침의 범위에 액세스 할 수 없습니다 :

AnglularJS: Creating Custom Directives

이 transclude 옵션이 수행하는 일 , 정확히? transclude는이 옵션을 가진 지시문의 내용이 지시문 외부의 범위가 아닌 내부의 범위에 액세스 할 수 있도록합니다.

.directive('myList', function() { 
    return { 
    restrict: 'E', 
    transclude: true, 
    scope: { items: '=' }, 
    template: '<div ng-repeat="item in items" inject></div>' 
    }; 
}) 

.directive('inject', function() { 
    return { 
    link: function($scope, $element, $attrs, controller, $transclude) { 
     $transclude($scope, function(clone) { 
     $element.empty(); 
     $element.append(clone); 
     }); 
    } 
    }; 
}) 

<my-list items="articles"> 
    <strong>{{item.title}}</strong> by <span>{{item.author}}</span> 
</my-list> 

이 토론에서 찍은 :

그래서 해결책은 다음과 같이 지시어 내에서 템플릿의 범위를 주입하는 다른 구성 요소를 만드는 것입니다 #7874

그리고 나는 Plnkr했다 .

+0

나는 목록의 크기를 처리하는 코드를 솔루션에 포함시키지 않았습니다. "+5 이상"을 포함하지만 쉬운 부분입니다. – Vinicius

관련 문제