बिना html एलिमेंट के एनजी-रिपीट का उपयोग कैसे करें


142

मुझे उपयोग करने की आवश्यकता है ng-repeat (एंगुलरजेएस में) एरे में सभी तत्वों को सूचीबद्ध करने की आवश्यकता है।

जटिलता यह है कि सरणी का प्रत्येक तत्व तालिका की एक, दो या तीन पंक्तियों में बदल जाएगा।

मैं मान्य HTML नहीं बना सकता, अगर ng-repeatकिसी तत्व पर प्रयोग किया जाता है, क्योंकि किसी भी प्रकार के दोहराए जाने वाले तत्व के बीच अनुमति नहीं है <tbody>और <tr>

उदाहरण के लिए, अगर मैंने एनजी-रिपीट का इस्तेमाल किया, तो मुझे <span>मिलेगा:

<table>
  <tbody>
    <span>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
    </span>
  </tbody>
</table>          

जो अमान्य HTML है।

लेकिन जो मुझे उत्पन्न करने की आवश्यकता है वह है:

<table>
  <tbody>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
  </tbody>
</table>          

जहां पहली पंक्ति पहले सरणी तत्व द्वारा उत्पन्न हुई है, अगले तीन दूसरे और पांचवें और छठे अंतिम सरणी तत्व द्वारा।

मैं एनजी-रिपीट का उपयोग इस तरह से कैसे कर सकता हूं कि HTML तत्व, जिसके लिए यह रेंडरिंग के दौरान 'गायब' है?

या इसका कोई और उपाय है?


स्पष्टीकरण: उत्पन्न संरचना नीचे की तरह दिखनी चाहिए। प्रत्येक सरणी तत्व तालिका की 1-3 पंक्तियों के बीच उत्पन्न हो सकता है। उत्तर को आदर्श तत्व के लिए 0-n पंक्तियों का आदर्श रूप से समर्थन करना चाहिए।

<table>
  <tbody>
    <!-- array element 0 -->
    <tr>
      <td>One row item</td>
    </tr>
    <!-- array element 1 -->
    <tr>
      <td>Three row item</td>
    </tr>
    <tr>
      <td>Some product details</td>
    </tr>
    <tr>
      <td>Customer ratings</td>
    </tr>
    <!-- array element 2 -->
    <tr>
      <td>Two row item</td>
    </tr>
    <tr>
      <td>Full description</td>
    </tr>
  </tbody>
</table>          

शायद आपको "प्रतिस्थापित: सच" का उपयोग करना चाहिए? इसे देखें: stackoverflow.com/questions/11426114/…

इसके अलावा, आप tr पर एनजी-रिपीट का उपयोग क्यों नहीं कर सकते हैं?

2
@ टॉमी, क्योंकि "सरणी का प्रत्येक तत्व तालिका के एक, दो या तीन पंक्तियों में बदल जाएगा"। अगर मैं एनजी-रिपीट का इस्तेमाल करता trहूं तो मुझे एक पंक्ति प्रति सरणी तत्व मिलेगा, जहां तक ​​मैं समझता हूं।
फेदेबी

1
ठीक है मैं समझा। आप इसे पुनरावर्तक में उपयोग करने से पहले सिर्फ मॉडल को समतल नहीं कर सकते हैं?

@ टॉमी, नहीं। 1-3 trएस जो एक सरणी तत्व द्वारा उत्पन्न होते हैं, उनमें समान संरचना नहीं होती है।
फ़ेडबीबी

जवाबों:


66

अद्यतन: यदि आप कोणीय 1.2+ का उपयोग कर रहे हैं, तो एनजी-रिपीट-स्टार्ट का उपयोग करें । देखिए @ jmagnusson का जवाब

अन्यथा, एनओबी-दोहराने को टीओबी पर कैसे रखा जाए? (AFAIK, एकल तालिका में एकाधिक <tbody> s होना ठीक है।)

<tbody ng-repeat="row in array">
  <tr ng-repeat="item in row">
     <td>{{item}}</td>
  </tr>
</tbody>

62
हालांकि यह तकनीकी रूप से काम कर सकता है, यह बहुत निराशाजनक है कि इस सामान्य उपयोग के मामले का उत्तर यह है कि आपको मनमाने तरीके से इंजेक्शन लगाना होगा (अन्यथा अनावश्यक) मार्कअप। मुझे एक ही समस्या है (पंक्तियों के बार-बार समूह - एक हेडर टीआर एक या अधिक बच्चे टीआर के साथ, एक समूह के रूप में दोहराया गया)। अन्य टेम्पलेट इंजन के साथ तुच्छ, ऐसा लगता है कि कोणीय के साथ सबसे अच्छा हैकी।
ब्रायन Moeskau

1
माना। मैं डीटी + डीडी तत्वों पर एक दोहराने की कोशिश कर रहा हूं। वहाँ कोई रास्ता नहीं है कि एक अवैध लपेटकर तत्व को जोड़ने के बिना
डेविड लिन

2
@DavidLin, Angular v1.2 में (जब भी यह सामने आता है) आप कई तत्वों, जैसे, dt और dd पर दोहरा पाएंगे: youtube.com/watch?v=W13qDdJDHp8&t=1782828
मार्क राजकॉक

यह कंटेनर नियंत्रण नियंत्रण सिंटैक्स का उपयोग करके KnockoutJS में कुशलता से नियंत्रित किया जाता है: knockoutjs.com/documentation/foreach-binding.html । उम्मीद है कि एंगुलर जल्द ही कुछ ऐसा कर पाएंगे।
Cory हाउस

3
यह उत्तर पुराना है, इसके बजाय एनजी-रिपीट-स्टार्ट का उपयोग करें
iwein

73

AngularJS 1.2 के रूप में वहाँ एक निर्देश कहा जाता है ng-repeat-startजो वास्तव में आप क्या मांगते हैं। इसका उपयोग कैसे करें, इसका वर्णन करने के लिए इस प्रश्न में मेरा उत्तर देखें ।


कोणीय ने पकड़ लिया है, यह अब उचित समाधान है।
इविन

33

यदि आप एनजी> 1.2 का उपयोग करते हैं, तो यहां ng-repeat-start/endअनावश्यक टैग उत्पन्न किए बिना उपयोग करने का एक उदाहरण है :

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
      angular.module('mApp', []);
    </script>
  </head>
  <body ng-app="mApp">
    <table border="1" width="100%">
      <tr ng-if="0" ng-repeat-start="elem in [{k: 'A', v: ['a1','a2']}, {k: 'B', v: ['b1']}, {k: 'C', v: ['c1','c2','c3']}]"></tr>

      <tr>
        <td rowspan="{{elem.v.length}}">{{elem.k}}</td>
        <td>{{elem.v[0]}}</td>
      </tr>
      <tr ng-repeat="v in elem.v" ng-if="!$first">
        <td>{{v}}</td>
      </tr>

      <tr ng-if="0" ng-repeat-end></tr>
    </table>
  </body>
</html>

महत्वपूर्ण बिंदु: पृष्ठ में सम्मिलित नहीं होने देने के लिए ng-repeat-startऔर ng-repeat-endसेट के लिए उपयोग किए जाने वाले टैग के लिए ng-if="0"। इस तरह आंतरिक सामग्री को ठीक उसी तरह संभाला जाएगा जैसा कि यह नॉकआउट (कमांड्स का उपयोग करके <!--...-->) में है, और कोई कचरा नहीं होगा।


एनजी-अगर = "0" सेट करने के बाद, यह त्रुटि को यह कहते हुए फेंक देता है कि एनजी-रिपीट-एंड का मिलान करने में असमर्थ है।
विकी MCTS

19

आप अपने नियंत्रक के भीतर डेटा को समतल करना चाहते हैं:

function MyCtrl ($scope) {
  $scope.myData = [[1,2,3], [4,5,6], [7,8,9]];
  $scope.flattened = function () {
    var flat = [];
    $scope.myData.forEach(function (item) {
      flat.concat(item);
    }
    return flat;
  }
}

और फिर HTML में:

<table>
  <tbody>
    <tr ng-repeat="item in flattened()"><td>{{item}}</td></tr>
  </tbody>
</table>

1
नहीं यह नहीं। एक एनकैपिट अभिव्यक्ति के अंदर एक फ़ंक्शन को कॉल करना बिल्कुल अनुशंसित नहीं है
निक

मेरे मामले में, मुझे प्रत्येक तत्व के लिए एक विभाजक जोड़ने की आवश्यकता थी जहां सूचकांक! = 0 और ng-repeat-start, ng-repeat-endमेरे डिज़ाइन को तोड़ दें, इसलिए समाधान था कि प्रत्येक तत्व से पहले इस विभाजक वस्तु को जोड़ने के लिए एक अतिरिक्त चर बनाया जाए और नए <div class="c477_group"> <div class="c477_group_item" ng-repeat="item in itemsWithSeparator" ng-switch="item.id" ng-class="{'-divider' : item.id == 'SEPARATOR'}"> <div class="c478" ng-switch-when="FAS"/> <div class="c478" ng-switch-when="SEPARATOR" /> <div class="c479" ng-switch-default /> </div> </div>
संस्करण को पुन

6

उपरोक्त सही है, लेकिन अधिक सामान्य उत्तर के लिए यह पर्याप्त नहीं है। मुझे एनजी-रिपीट करने की आवश्यकता थी, लेकिन एक ही एचटीएमएल स्तर पर रहना, जिसका अर्थ है एक ही मूल में तत्व लिखना। टैग सरणी में टैग होते हैं जिनमें टैग सरणी भी होती है। यह वास्तव में एक पेड़ है।

[{ name:'name1', tags: [
  { name: 'name1_1', tags: []},
  { name: 'name1_2', tags: []}
  ]},
 { name:'name2', tags: [
  { name: 'name2_1', tags: []},
  { name: 'name2_2', tags: []}
  ]}
]

तो यहाँ वही है जो मैंने अंततः किया।

<div ng-repeat-start="tag1 in tags" ng-if="false"></div>
    {{tag1}},
  <div ng-repeat-start="tag2 in tag1.tags" ng-if="false"></div>
    {{tag2}},
  <div ng-repeat-end ng-if="false"></div>
<div ng-repeat-end ng-if="false"></div>

एनजी-अगर = "झूठे" पर ध्यान दें जो प्रारंभ और अंत div को छुपाता है।

इसे छापना चाहिए

name1, name1_1, name1_2, NAME2 name2_1, name2_2,


1

मैं सिर्फ टिप्पणी करना चाहूंगा, लेकिन मेरी प्रतिष्ठा में अभी भी कमी है। तो मैं एक और समाधान जोड़ रहा हूं जो समस्या को हल करता है। मैं वास्तव में @bmoeskau द्वारा दिए गए उस कथन का खंडन करना चाहूंगा कि इस समस्या को हल करने के लिए 'सबसे अच्छे तरीके से हैकी' समाधान की आवश्यकता होती है, और चूंकि यह हाल ही में एक चर्चा में आया था, हालांकि यह पोस्ट 2 साल पुरानी है, मैं इसे जोड़ना चाहूंगा खुद के दो सेंट:

जैसा कि @btford ने बताया है, आप एक पुनरावर्ती संरचना को एक सूची में बदलने की कोशिश कर रहे हैं, इसलिए आपको पहले उस संरचना को सूची में समतल करना चाहिए। उसका समाधान यही करता है, लेकिन एक राय है कि टेम्पलेट के अंदर फ़ंक्शन को कॉल करना अयोग्य है। अगर यह सच है (ईमानदारी से, मुझे पता नहीं है) कि निर्देशक के बजाय नियंत्रक में फ़ंक्शन को निष्पादित करने की आवश्यकता नहीं होगी?

किसी भी तरह से, आपके html को एक सूची की आवश्यकता होती है, इसलिए यह जो गुंजाइश प्रदान करता है, उस सूची के साथ काम करना चाहिए। आपको बस अपने नियंत्रक के अंदर संरचना को समतल करना होगा। एक बार जब आपके पास $ गुंजाइश होगी। सरणी, आप एकल, सरल एनजी-दोहराने के साथ तालिका उत्पन्न कर सकते हैं। कोई हैकिंग नहीं, कोई असमानता नहीं, बस जिस तरह से यह काम करने के लिए डिज़ाइन किया गया था।

कोणीय निर्देशों में कार्यक्षमता की कमी नहीं है। वे बस आपको वैध html लिखने के लिए मजबूर करते हैं। मेरे एक सहकर्मी ने एक समान मुद्दा रखा था, जो कोणीय टेम्परिंग या प्रतिपादन सुविधाओं पर आलोचना के समर्थन में @bmoeskau का हवाला देता है। जब सटीक समस्या को देखते हुए, यह पता चला कि वह बस एक खुला-टैग उत्पन्न करना चाहता था, तो कहीं और एक करीबी टैग, आदि .. जैसे अच्छे पुराने दिनों में जब हम स्ट्रिंग्स से अपने HTML को गुप्त करेंगे .. सही? नहीं।

एक सूची में संरचना को समतल करने के लिए, यहां एक और समाधान है:

// assume the following structure
var structure = [
    {
        name: 'item1', subitems: [
            {
                name: 'item2', subitems: [
                ],
            }
        ],
    }
];
var flattened = structure.reduce((function(prop,resultprop){
    var f = function(p,c,i,a){
        p.push(c[resultprop]);
        if (c[prop] && c[prop].length > 0 )
          p = c[prop].reduce(f,p);
        return p;
    }
    return f;
})('subitems','name'),[]);

// flattened now is a list: ['item1', 'item2']

यह किसी भी पेड़ जैसी संरचना के लिए काम करेगा जिसमें उप आइटम हों। यदि आप एक संपत्ति के बजाय पूरे आइटम चाहते हैं, तो आप समतल फ़ंक्शन को और भी छोटा कर सकते हैं।

उम्मीद है की वो मदद करदे।


अच्छा है। हालांकि इससे मुझे सीधे मदद नहीं मिली, लेकिन इसने मेरे दिमाग को दूसरे समाधान के लिए खोल दिया। आपका बहुत बहुत धन्यवाद!
मैरिएन ज़र्बलिक

0

एक समाधान के लिए जो वास्तव में काम करता है

एचटीएमएल

<remove  ng-repeat-start="itemGroup in Groups" ></remove>
   html stuff in here including inner repeating loops if you want
<remove  ng-repeat-end></remove>

एक कोणीय जोड़ें। निर्देश

//remove directive
(function(){
    var remove = function(){

        return {    
            restrict: "E",
            replace: true,
            link: function(scope, element, attrs, controller){
                element.replaceWith('<!--removed element-->');
            }
        };

    };
    var module = angular.module("app" );
    module.directive('remove', [remove]);
}());

एक संक्षिप्त विवरण के लिए,

एनजी-रिपीट खुद को बांधता है <remove> तत्व के रूप में और इसे वैसे ही लूप करना चाहिए, और क्योंकि हमने एनजी-रिपीट-स्टार्ट / एनजी-रिपीट-एंड का इस्तेमाल किया है, यह html का एक ब्लॉक लूप है, न कि केवल एक तत्व।

तब कस्टम हटाने के निर्देश देता है <remove>और तत्वों को शुरू और खत्म करता है<!--removed element-->


-2
<table>
  <tbody>
    <tr><td>{{data[0].foo}}</td></tr>
    <tr ng-repeat="d in data[1]"><td>{{d.bar}}</td></tr>
    <tr ng-repeat="d in data[2]"><td>{{d.lol}}</td></tr>
  </tbody>
</table>

मुझे लगता है कि यह वैध है :)


जबकि यह काम करता है, यह केवल तभी काम करेगा जब सरणी में तीन तत्व हों।
बीटीफोर्ड

बस यह सुनिश्चित करें कि सरणी में 3 तत्व हैं, भले ही वे खाली सरणियाँ हों (खाली सरणी के साथ एनजी-रिपीट बस कुछ भी प्रस्तुत न करें)।
रेयान तोमल फर्नांडिस

7
मेरा कहना था कि ओपी संभवत: एक समाधान चाहता है जो सरणी में मदों की एक चर संख्या के लिए काम करता है। मेरा मानना ​​है कि "इस सरणी में तीन आइटम होने चाहिए" टेम्पलेट में एक खराब समाधान होगा।
बीटीफोर्ड

अपने सवाल पर अंतिम टिप्पणी में उन्होंने कहा कि तत्वों में एक ही संरचना नहीं होगी, इसलिए प्रत्येक संरचना को हार्डकोड करना अपरिहार्य है।
रेयान तोमल फर्नांडिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.