एक हैंडलबार.जेएस {{#if}} सशर्त में लॉजिकल ऑपरेटर


479

क्या हैंडलबार जेएस में तार्किक ऑपरेटर को मानक हैंडलबार.जेएस सशर्त ऑपरेटर में शामिल करने का एक तरीका है? कुछ इस तरह:

{{#if section1 || section2}}
.. content
{{/if}}

मुझे पता है कि मैं अपना खुद का सहायक लिख सकता हूं, लेकिन पहले मैं यह सुनिश्चित करना चाहता हूं कि मैं पहिया को सुदृढ़ नहीं कर रहा हूं।

जवाबों:


518

यह ब्लॉक हेल्पर के साथ 'धोखा' से संभव है। यह संभवत: उन लोगों की विचारधारा के खिलाफ जाता है जिन्होंने हैंडलबार विकसित किए।

Handlebars.registerHelper('ifCond', function(v1, v2, options) {
  if(v1 === v2) {
    return options.fn(this);
  }
  return options.inverse(this);
});

फिर आप इस तरह से टेम्पलेट में सहायक को कॉल कर सकते हैं

{{#ifCond v1 v2}}
    {{v1}} is equal to {{v2}}
{{else}}
    {{v1}} is not equal to {{v2}}
{{/ifCond}}

54
यह हैंडलबार्स / मूंछों के तर्कहीन स्वभाव के खिलाफ जाता है, लेकिन फिर भी निश्चित रूप से उपयोगी है, धन्यवाद!
बाला क्लार्क

6
ध्यान दें कि यह केवल बाध्य गुणों के साथ काम नहीं करता है (पढ़ें, एम्बर बाइंडिंग)। यह शाब्दिक मूल्यों के साथ ठीक है, लेकिन मॉडल गुणों (एम्बर 1.0.0-आरसी.8 और हैंडलबार 1.0.0 के साथ परीक्षण) को हल नहीं करता है, और registerBoundHelperहैंडलबार सिंटैक्स के साथ सौदा नहीं कर सकता है। वर्कअराउंड एक कस्टम दृश्य बनाने के लिए है: stackoverflow.com/questions/18005111/…
वॉरेन सीन

28
@ बाला क्लार्क हालांकि यह वास्तव में तर्कहीन है? मेरा मतलब है कि यह अभी भी "अगर" बयान है - सिर्फ इसलिए कि वे जानबूझकर अपंग हैं दर्शन को नहीं बदलते हैं।
फ्राकहेड

111
मुझे कभी समझ नहीं आया कि डेवलपर्स खुद को हैंडीकैप करना क्यों पसंद करते हैं।
स्टैकऑवरफ्लो

36
मुझे समझ में नहीं आता कि क्यों और / या हैंडलबार्स का हिस्सा नहीं हो सकता। यह तर्कहीन प्रकृति के खिलाफ नहीं जाता है क्योंकि वहां पहले से ही IF, UNLESS, और EACH ... बहुत कुछ है ...
Asaf

445

समाधान एक कदम आगे बढ़ाते हुए। यह तुलना ऑपरेटर जोड़ता है।

Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {

    switch (operator) {
        case '==':
            return (v1 == v2) ? options.fn(this) : options.inverse(this);
        case '===':
            return (v1 === v2) ? options.fn(this) : options.inverse(this);
        case '!=':
            return (v1 != v2) ? options.fn(this) : options.inverse(this);
        case '!==':
            return (v1 !== v2) ? options.fn(this) : options.inverse(this);
        case '<':
            return (v1 < v2) ? options.fn(this) : options.inverse(this);
        case '<=':
            return (v1 <= v2) ? options.fn(this) : options.inverse(this);
        case '>':
            return (v1 > v2) ? options.fn(this) : options.inverse(this);
        case '>=':
            return (v1 >= v2) ? options.fn(this) : options.inverse(this);
        case '&&':
            return (v1 && v2) ? options.fn(this) : options.inverse(this);
        case '||':
            return (v1 || v2) ? options.fn(this) : options.inverse(this);
        default:
            return options.inverse(this);
    }
});

इसे इस तरह से एक टेम्पलेट में उपयोग करें:

{{#ifCond var1 '==' var2}}

कॉफी स्क्रिप्ट संस्करण

Handlebars.registerHelper 'ifCond', (v1, operator, v2, options) ->
    switch operator
        when '==', '===', 'is'
            return if v1 is v2 then options.fn this else options.inverse this
        when '!=', '!=='
            return if v1 != v2 then options.fn this else options.inverse this
        when '<'
            return if v1 < v2 then options.fn this else options.inverse this
        when '<='
            return if v1 <= v2 then options.fn this else options.inverse this
        when '>'
            return if v1 > v2 then options.fn this else options.inverse this
        when '>='
            return if v1 >= v2 then options.fn this else options.inverse this
        when '&&', 'and'
            return if v1 and v2 then options.fn this else options.inverse this
        when '||', 'or'
            return if v1 or v2 then options.fn this else options.inverse this
        else
            return options.inverse this

20
'||'और के बारे में मत भूलना '&&'। मैंने इन मामलों को जोड़ा और वे बहुत उपयोगी हैं।
जेसन

20
एक चीज़ को हैंडल करने के लिए एक noob होने के नाते जो स्पष्ट नहीं था कि आपको ऑपरेटर को एक स्ट्रिंग के रूप में पास करना होगा या अन्यथा कंपाइलर आपके टेम्पलेट को टोकन करते समय त्रुटि करेगा। {{#ifCond true '==' झूठी '}
जो

2
मैंने पाया कि मूल्यों का मूल्यांकन वस्तु विशेषताओं के लिए नहीं किया जाना चाहिए। निम्नलिखित जोड़ने से मदद मिलती है v1 = Ember.Handlebars.get(this, v1, options) v2 = Ember.Handlebars.get(this, v2, options)
ZX12R

4
लेकिन अगर v1 और v2 भी एक शर्त है तो मैं कैसे उपयोग कर सकता हूं? for ex: if (value == "a" || value == "b")
कृष्णा

3
यदि आप इसके साथ एक और कर सकते हैं?
jbyrd

160

हैंडलबार नेस्टेड ऑपरेशन का समर्थन करता है। यदि हम अपने तर्क को थोड़ा अलग तरीके से लिखते हैं तो यह बहुत अधिक लचीलापन (और क्लीनर कोड) प्रदान करता है।

{{#if (or section1 section2)}}
.. content
{{/if}}

वास्तव में, हम सभी प्रकार के तर्क जोड़ सकते हैं:

{{#if (or 
        (eq section1 "foo")
        (ne section2 "bar"))}}
.. content
{{/if}}

बस इन सहायकों को पंजीकृत करें:

Handlebars.registerHelper({
    eq: (v1, v2) => v1 === v2,
    ne: (v1, v2) => v1 !== v2,
    lt: (v1, v2) => v1 < v2,
    gt: (v1, v2) => v1 > v2,
    lte: (v1, v2) => v1 <= v2,
    gte: (v1, v2) => v1 >= v2,
    and() {
        return Array.prototype.every.call(arguments, Boolean);
    },
    or() {
        return Array.prototype.slice.call(arguments, 0, -1).some(Boolean);
    }
});

5
ध्यान दें कि यह Ember 1.10 में HTMLBars तक संभव नहीं था। इसके अलावा, यदि आप चाहते हैं तो उन सहायकों को एक एम्बर सीएलआई एडऑन के रूप में आता है: github.com/jmurphyau/ember-truth-helpers
Stephen.hanson

1
इस तरह, बिना किसी optionsनिष्पादन के साथ ifपद्धति को बनाए रखना बेहतर है और परीक्षण करना आसान है। धन्यवाद!
वाशिंगटन Botelho

25
हमें लगता है कि लिस्प को हैंडलबार्स में बनाया गया है।
jdunning

8
आपके andऔर orसहायक केवल 2 मापदंडों के साथ काम करते हैं, जो आप नहीं चाहते हैं। मैं दो से अधिक मापदंडों का समर्थन करने के लिए दोनों सहायकों andऔर orसहायकों को फिर से तैयार करने में कामयाब रहा । के लिए इस एक लाइनर का प्रयोग करें and: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);और के लिए इस एक लाइनर का उपयोग or: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);
ल्यूक

3
एक छोटे से अधिक उन्नत संस्करण है कि प्रत्येक ऑपरेटर पर एक से अधिक पैरामीटर ले सकते हैं।
नैट

87

यह एक पायदान ऊपर ले जाना, आप में से उन लोगों के लिए जो किनारे पर रहते हैं।

gist : https://gist.github.com/akhoury/9118682 डेमो : नीचे कोड स्निपेट

हैंडलबार्स हेल्पर: {{#xif EXPRESSION}} {{else}} {{/xif}}

किसी भी अभिव्यक्ति के साथ एक IF कथन निष्पादित करने के लिए सहायक

  1. अभिव्यक्ति एक अच्छी तरह से बच स्ट्रिंग है
  2. हाँ, आप की जरूरत है ठीक से स्ट्रिंग शाब्दिक या सिर्फ वैकल्पिक सिंगल और डबल उद्धरण से बचने के लिए
  3. आप किसी भी वैश्विक समारोह या संपत्ति का उपयोग कर सकते हैं encodeURIComponent(property)
  4. यह उदाहरण मानता है कि आपने इस संदर्भ को अपने हैंडलबार में भेज template( {name: 'Sam', age: '20' } )दिया ageहै , नोटिस एक है string, बस इसलिए मैं parseInt()इस पोस्ट में बाद में डेमो कर सकता हूं

उपयोग:

<p>
 {{#xif " name == 'Sam' && age === '12' " }}
   BOOM
 {{else}}
   BAMM
 {{/xif}}
</p>

उत्पादन

<p>
  BOOM
</p>

जावास्क्रिप्ट: (यह दूसरे सहायक पर निर्भर करता है- पढ़ना जारी रखें)

 Handlebars.registerHelper("xif", function (expression, options) {
    return Handlebars.helpers["x"].apply(this, [expression, options]) ? options.fn(this) : options.inverse(this);
  });

हैंडलबार्स हेल्पर: {{x EXPRESSION}}

जावास्क्रिप्ट अभिव्यक्ति निष्पादित करने के लिए एक सहायक

  1. अभिव्यक्ति एक अच्छी तरह से बच स्ट्रिंग है
  2. हाँ, आप की जरूरत है ठीक से स्ट्रिंग शाब्दिक या सिर्फ वैकल्पिक सिंगल और डबल उद्धरण से बचने के लिए
  3. आप किसी भी वैश्विक समारोह या संपत्ति का उपयोग कर सकते हैं parseInt(property)
  4. इस उदाहरण मानता है कि आप अपने हैंडल करने के लिए इस संदर्भ पारित कर दिया template( {name: 'Sam', age: '20' } ), ageएक है stringकुछ भी डेमो प्रयोजन के लिए, यह हो सकता है ..

उपयोग:

<p>Url: {{x "'hi' + name + ', ' + window.location.href + ' <---- this is your href,' + ' your Age is:' + parseInt(this.age, 10)"}}</p>

आउटपुट:

<p>Url: hi Sam, http://example.com <---- this is your href, your Age is: 20</p>

जावास्क्रिप्ट:

यह थोड़ा बड़ा लगता है क्योंकि मैंने वाक्य रचना का विस्तार किया और स्पष्टता के उद्देश्य से लगभग प्रत्येक पंक्ति पर टिप्पणी की

Handlebars.registerHelper("x", function(expression, options) {
  var result;

  // you can change the context, or merge it with options.data, options.hash
  var context = this;

  // yup, i use 'with' here to expose the context's properties as block variables
  // you don't need to do {{x 'this.age + 2'}}
  // but you can also do {{x 'age + 2'}}
  // HOWEVER including an UNINITIALIZED var in a expression will return undefined as the result.
  with(context) {
    result = (function() {
      try {
        return eval(expression);
      } catch (e) {
        console.warn('•Expression: {{x \'' + expression + '\'}}\n•JS-Error: ', e, '\n•Context: ', context);
      }
    }).call(context); // to make eval's lexical this=context
  }
  return result;
});

Handlebars.registerHelper("xif", function(expression, options) {
  return Handlebars.helpers["x"].apply(this, [expression, options]) ? options.fn(this) : options.inverse(this);
});

var data = [{
  firstName: 'Joan',
  age: '21',
  email: 'joan@aaa.bbb'
}, {
  firstName: 'Sam',
  age: '18',
  email: 'sam@aaa.bbb'
}, {
  firstName: 'Perter',
  lastName: 'Smith',
  age: '25',
  email: 'joseph@aaa.bbb'
}];

var source = $("#template").html();
var template = Handlebars.compile(source);
$("#main").html(template(data));
h1 {
  font-size: large;
}
.content {
  padding: 10px;
}
.person {
  padding: 5px;
  margin: 5px;
  border: 1px solid grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js"></script>

<script id="template" type="text/x-handlebars-template">
  <div class="content">
    {{#each this}}
    <div class="person">
      <h1>{{x  "'Hi ' + firstName"}}, {{x 'lastName'}}</h1>
      <div>{{x '"you were born in " + ((new Date()).getFullYear() - parseInt(this.age, 10)) '}}</div>
      {{#xif 'parseInt(age) >= 21'}} login here:
      <a href="http://foo.bar?email={{x 'encodeURIComponent(email)'}}">
        	http://foo.bar?email={{x 'encodeURIComponent(email)'}}
        </a>
      {{else}} Please go back when you grow up. {{/xif}}
    </div>
    {{/each}}
  </div>
</script>

<div id="main"></div>

Moar

यदि आप ऊपरी स्तर के दायरे तक पहुंच चाहते हैं, तो यह थोड़ा अलग है, अभिव्यक्ति सभी तर्कों का JOIN है, उपयोग: संदर्भ डेटा इस तरह दिखता है:

// data
{name: 'Sam', age: '20', address: { city: 'yomomaz' } }

// in template
// notice how the expression wrap all the string with quotes, and even the variables
// as they will become strings by the time they hit the helper
// play with it, you will immediately see the errored expressions and figure it out

{{#with address}}
    {{z '"hi " + "' ../this.name '" + " you live with " + "' city '"' }}
{{/with}}

जावास्क्रिप्ट:

Handlebars.registerHelper("z", function () {
    var options = arguments[arguments.length - 1]
    delete arguments[arguments.length - 1];
    return Handlebars.helpers["x"].apply(this, [Array.prototype.slice.call(arguments, 0).join(''), options]);
});

Handlebars.registerHelper("zif", function () {
    var options = arguments[arguments.length - 1]
    delete arguments[arguments.length - 1];
    return Handlebars.helpers["x"].apply(this, [Array.prototype.slice.call(arguments, 0).join(''), options]) ? options.fn(this) : options.inverse(this);
});

15
यह भी खूब रही। हैंडलबार्स आपको बता नहीं सकता कि क्या करना है :)
lemiant

1
:) धन्यवाद, मैं अद्यतन सार एक छोटे से कुछ और उपहार जोड़ने के लिए (सीधे इस अतः प्रश्न से संबंधित नहीं है - लेकिन क्या आप एक हैंडल टेम्पलेट के अंदर चाहते कर की भावना में) लेकिन, आप सीमाओं के लिए बाहर देखना चाहिए, मैं हेवन अभिव्यक्ति के भीतर से "ऊपरी गुंजाइश के स्तर" तक पहुंचने का एक तरीका मिला, कहते हैं कि आप प्रत्येक दायरे में हैं, {{#each}} ... {{xif ' ../name === this.name' }} {{/each}}... लेकिन मैं अभी भी जांच कर रहा हूं ..
bentael

1
"ऊपरी स्कोप एक्सेस" के लिए एक समाधान मिला, लेकिन एक नए सहायक का उपयोग करके, अपडेट किया गया उत्तर देखें, {{z ...}}सहायक
बेंटेल

बूम! बहुत बढ़िया, अब मैं अपने आंशिक धन्यवाद के अंदर वास्तविक स्थिति कर सकता हूं !
एकिनू

1
@rickysullivan इसके eval(expression);साथ अपनी जगह लेने की कोशिश करें: eval('(function(){try{return ' + expression + ';}catch(e){}})();');- मुझे पता है कि यह बदसूरत हो रहा है, लेकिन ऐसा करने का एक सुरक्षित तरीका नहीं सोच सकता - कृपया ध्यान रखें कि यह निष्पादित करने के लिए बहुत "तेज़" नहीं है, मैं इसमें ऐसा नहीं करूंगा भारी चलना।
बेंटेल

33

सहायक कार्य लिखे बिना ऐसा करने का एक सरल तरीका है ... यह पूरी तरह से टेम्पलेट के भीतर किया जा सकता है।

{{#if cond1}}   
  {{#if con2}}   
    <div> and condition completed</div>  
  {{/if}}
{{else}}   
  <div> both conditions weren't true</div>  
{{/if}}

संपादित करें: इसके विपरीत आप यह कर या कर सकते हैं:

{{#if cond1}}  
  <div> or condition completed</div>    
{{else}}   
  {{#if cond2}}  
    <div> or condition completed</div>  
  {{else}}      
    <div> neither of the conditions were true</div>    
  {{/if}}  
{{/if}}

संपादित करें / ध्यान दें: हैंडलबार की वेबसाइट से: handlebarsjs.com यहाँ झूठे मूल्य हैं:

यदि हेल्पर किसी ब्लॉक को सशर्त रूप से प्रस्तुत करने के लिए उपयोग कर सकता है। यदि इसका तर्क गलत, अपरिभाषित, अशक्त, "" या [] ("गलत" मूल्य) देता है, तो किसी भी 'cond' (जैसे cond1 या cond2) को सही नहीं माना जाएगा।


9
वास्तव में, आप दो मूल्य की तुलना नहीं करते हैं, आप यह सुनिश्चित करते हैं कि दोनों मौजूद हैं, यह अलग है।
सिरिल एन।

3
वास्तव में यह उसी तरह से मूल्यांकन करता है जिस तरह से जावास्क्रिप्ट वेबसाइट से करता है: "यदि आप किसी ब्लॉक को रेंडर करने के लिए हेल्पर का उपयोग कर सकते हैं। यदि उसका तर्क गलत, अपरिभाषित, अशक्त," या [] ("काल्पनिक" मान) देता है। हैंडलबार ब्लॉक को रेंडर नहीं करेंगे। ”
जोनो सेप

1
आप सही हैं, मैंने पहले सोचा था कि परीक्षण दो मूल्यों की तुलना करने के लिए था, दोनों का परीक्षण मौजूद नहीं था। मेरा बुरा, क्षमा करें।
सिरिल एन।

4
यह सही ढंग से काम नहीं करता है। अगर cond1 सच है और con2 गलत है, तो कुछ भी प्रिंट नहीं किया जाएगा।
टेसा लाउ

1
हे @TessaLau, मुझे लगता है कि मैं देख रहा हूँ कि तुम कहाँ से आ रहे हैं। हालाँकि, यदि आप एक नियंत्रण प्रवाह निकालते हैं, तो आप देखेंगे कि पहली पंक्ति में नियंत्रण प्रवाह को उस स्थिति में ले जाता है।
जोनो

19

यहां पोस्ट किए गए सभी उत्तरों के साथ एक समस्या यह है कि वे बाध्य गुणों के साथ काम नहीं करते हैं, अर्थात जब गुण बदलते हैं तो स्थिति का पुनर्मूल्यांकन नहीं किया जाता है। यहाँ सहायक सहायक बाइंडिंग का थोड़ा और उन्नत संस्करण है। यह एम्बर स्रोत से बाइंड फ़ंक्शन का उपयोग करता है , जिसका उपयोग सामान्य एम्बर को लागू करने के लिए भी किया जाता है#if सहायक ।

यह एक बाएं हाथ की ओर एक एकल बंधी हुई संपत्ति तक सीमित है, जो दाएं-हाथ की तरफ एक निरंतरता की तुलना में है, जो मुझे लगता है कि अधिकांश व्यावहारिक उद्देश्यों के लिए पर्याप्त है। यदि आपको एक साधारण तुलना की तुलना में कुछ अधिक उन्नत की आवश्यकता है, तो शायद कुछ कम्प्यूटेड संपत्तियों की घोषणा करना और #ifइसके बजाय सामान्य सहायक का उपयोग करना शुरू करना अच्छा होगा ।

Ember.Handlebars.registerHelper('ifeq', function(a, b, options) {
  return Ember.Handlebars.bind.call(options.contexts[0], a, options, true, function(result) {
    return result === b;
  });
});

आप इसे इस तरह से उपयोग कर सकते हैं:

{{#ifeq obj.some.property "something"}}
  They are equal!
{{/ifeq}}

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

2
क्या किसी ने HTMLBars / Ember 1.10 के साथ यह काम किया है? Ember.Handlebars.bind अब मौजूद नहीं है।
लिंडा

मैंने मूल रूप से registerBoundHelper का उपयोग किया था, लेकिन तब जब यह स्थिति बदल गई तो यह दूसरे मूल्य और पीछे नहीं बदलेगा। यह विधि बदलने के लिए अंगारे के साथ काम करती है :) इसमें बहुत अधिक वोट होने चाहिए
मैट वुकोमनोविच

13

बेहतर समाधान जो मूल रूप से किसी भी द्विआधारी ऑपरेटर के साथ काम करता है (कम से कम संख्या में, तार eval के साथ अच्छी तरह से काम नहीं करता है, टोकरे की स्थिति को ध्यान में रखते हुए अगर किसी व्यक्ति के लिए एक गैर-संचालित ऑपरेटर का उपयोग कर रहा है):

Handlebars.registerHelper("ifCond",function(v1,operator,v2,options) {
    switch (operator)
    {
        case "==":
            return (v1==v2)?options.fn(this):options.inverse(this);

        case "!=":
            return (v1!=v2)?options.fn(this):options.inverse(this);

        case "===":
            return (v1===v2)?options.fn(this):options.inverse(this);

        case "!==":
            return (v1!==v2)?options.fn(this):options.inverse(this);

        case "&&":
            return (v1&&v2)?options.fn(this):options.inverse(this);

        case "||":
            return (v1||v2)?options.fn(this):options.inverse(this);

        case "<":
            return (v1<v2)?options.fn(this):options.inverse(this);

        case "<=":
            return (v1<=v2)?options.fn(this):options.inverse(this);

        case ">":
            return (v1>v2)?options.fn(this):options.inverse(this);

        case ">=":
         return (v1>=v2)?options.fn(this):options.inverse(this);

        default:
            return eval(""+v1+operator+v2)?options.fn(this):options.inverse(this);
    }
});

आप इसे एक टेम्पलेट में कैसे उपयोग करेंगे? विशेष रूप से विकल्प। यदि भाग?
कोडीनिजा

{{ifCond val1 '|| val2}} true {{else}} false {{/ if}} यह विकल्प लौटाता है। यदि सही है, तो सही (अन्यथा, ifCond क्लॉज), अन्यथा यह options.inverse (गलत, अन्य क्लॉज) को गलत लौटाता है।
निक किट्टो

1
स्क्रिप्ट इंजेक्शन के बारे में उल्लेख किए जाने के कारण, मैं इस सहायक का उपयोग करने के खिलाफ दृढ़ता से सलाह दूंगा। एक बड़े कोडबेस में यह आसानी से लाइन के नीचे एक खराब सुरक्षा समस्या के लिए जिम्मेदार हो सकता है
जॉर्डन सिटकिन

8

यदि आप कई शर्तों की जांच करना चाहते हैं तो यहां एक समाधान है:

/* Handler to check multiple conditions
   */
  Handlebars.registerHelper('checkIf', function (v1,o1,v2,mainOperator,v3,o2,v4,options) {
      var operators = {
           '==': function(a, b){ return a==b},
           '===': function(a, b){ return a===b},
           '!=': function(a, b){ return a!=b},
           '!==': function(a, b){ return a!==b},
           '<': function(a, b){ return a<b},
           '<=': function(a, b){ return a<=b},
           '>': function(a, b){ return a>b},
           '>=': function(a, b){ return a>=b},
           '&&': function(a, b){ return a&&b},
           '||': function(a, b){ return a||b},
        }
      var a1 = operators[o1](v1,v2);
      var a2 = operators[o2](v3,v4);
      var isTrue = operators[mainOperator](a1, a2);
      return isTrue ? options.fn(this) : options.inverse(this);
  });

उपयोग:

/* if(list.length>0 && public){}*/

{{#checkIf list.length '>' 0 '&&' public '==' true}} <p>condition satisfied</p>{{/checkIf}}

7

यहाँ ब्लॉक हेल्पर I लिंक का उपयोग किया गया है: तुलना ब्लॉक हेल्पर । यह सभी मानक ऑपरेटरों का समर्थन करता है और आपको नीचे लिखे अनुसार कोड लिखने देता है। यह वास्तव में काफी आसान है।

{{#compare Database.Tables.Count ">" 5}}
There are more than 5 tables
{{/compare}}

1
यह जीतने वाला वोट होना चाहिए। मूल निवासी और इरादा। मुझे लगभग हर बार लगता है कि यदि आप एक नया सहायक लिख रहे हैं तो आप इसे उखाड़ फेंक रहे हैं।
अगस्त

2
@ यह एक देशी सहायक नहीं है। यदि आप लिंक का अनुसरण करते हैं तो आप देखेंगे कि यह एक कस्टम परिभाषित सहायक है।
गुफलम

@gfullam आप सही कह रहे हैं, मैं असेंबल में हैंडलबार का उपयोग कर रहा था, जिसमें यह सहायक मूल रूप से शामिल है। मेरी गलती।
augurone

4

जिम के जवाब के समान लेकिन थोड़ी रचनात्मकता का उपयोग करके हम भी कुछ ऐसा कर सकते हैं:

Handlebars.registerHelper( "compare", function( v1, op, v2, options ) {

  var c = {
    "eq": function( v1, v2 ) {
      return v1 == v2;
    },
    "neq": function( v1, v2 ) {
      return v1 != v2;
    },
    ...
  }

  if( Object.prototype.hasOwnProperty.call( c, op ) ) {
    return c[ op ].call( this, v1, v2 ) ? options.fn( this ) : options.inverse( this );
  }
  return options.inverse( this );
} );

फिर इसका उपयोग करने के लिए हमें कुछ ऐसा मिलता है:

{{#compare numberone "eq" numbretwo}}
  do something
{{else}}
  do something else
{{/compare}}

मैं बेहतर प्रदर्शन के लिए फ़ंक्शन को ऑब्जेक्ट से बाहर ले जाने का सुझाव दूंगा, लेकिन अन्यथा आप "और" और "या" सहित कोई भी तुलनात्मक फ़ंक्शन जोड़ सकते हैं।


3

एक अन्य विकल्प में फ़ंक्शन नाम का उपयोग करना है #if। यह #ifपता लगाएगा कि क्या पैरामीटर फंक्शन है और अगर ऐसा है तो वह इसे कॉल करेगा और सत्यता जांच के लिए इसकी वापसी का उपयोग करेगा। नीचे MyFunction को वर्तमान संदर्भ मिलता है this

{{#if myFunction}}
  I'm Happy!
{{/if}}

तो आपको संदर्भ में एक फ़ंक्शन जोड़ने की आवश्यकता होगी? कोड को किसी संदर्भ से बाहर निकालना एक सुरक्षा छेद है, क्योंकि कोड का स्रोत अज्ञात हो सकता है। XSS हमले के लिए इसका फायदा उठाया जा सकता है।
टी गुयेन 15

हां, आपको संदर्भ में फ़ंक्शन जोड़ने की आवश्यकता है। एक बुरी तरह से डिजाइन की गई वेबसाइट में, हाँ, यह सुरक्षा छेद हो सकता है। लेकिन उस मामले में, कई अन्य होंगे।
शीतल शाह

यह पसंदीदा तरीका है .. TY।
elad.chen 12

3

दुर्भाग्य से इनमें से कोई भी समाधान "OR" ऑपरेटर "cond1 || cond2" की समस्या को हल नहीं करता है।

  1. जाँच करें कि क्या प्रथम मान सत्य है
  2. "^" (या) का उपयोग करें और जांचें कि क्या cond2 सच है

    {{#if cond1}} DO ACTION {{^}} {{#if cond2}} DO ACTION {{/ if}} {{/ if}}

यह DRY नियम को तोड़ता है। तो इसे कम गन्दा करने के लिए आंशिक का उपयोग क्यों न करें

{{#if cond1}}
    {{> subTemplate}}
{{^}}
    {{#if cond2}}
        {{> subTemplate}}
    {{/if}}
{{/if}}

3

मैं समझ सकता हूं कि आप उन परिस्थितियों के लिए एक सहायक क्यों बनाना चाहते हैं, जहां आपके टेम्पलेट के भीतर प्रदर्शन करने के लिए आपके पास बड़ी संख्या में विविध तुलनाएं हैं, लेकिन तुलनात्मक रूप से अपेक्षाकृत कम संख्या के लिए (या एक भी, जो मुझे इस पृष्ठ में लाया गया था) पहले स्थान पर), आपके व्यू-रेंडरिंग फ़ंक्शन कॉल में नए हैंडलबार्स चर को परिभाषित करना आसान होगा:

रेंडर पर हैंडलबार्स पास करें:

var context= {
    'section1' : section1,
    'section2' : section2,
    'section1or2' : (section1)||(section2)
};

और फिर आपके हैंडलबार टेम्पलेट के भीतर:

{{#if section1or2}}
    .. content
{{/if}}

मैं सादगी के लिए इसका उल्लेख करता हूं, और यह भी क्योंकि यह एक उत्तर है जो हैंडलबार्स के तर्कहीन स्वभाव का अनुपालन करते हुए त्वरित और सहायक हो सकता है।


3

नीचे दिए गए कमांड को चलाकर एम्बर ट्रूथ हेल्पर्स ऐडऑन स्थापित करें

एम्बर एम्बर-सत्य-सहायकों को स्थापित करें

आप अधिकांश लॉजिकल ऑपरेटर्स (eq, not-eq, not, and, and, gt, gte, lt, lte, xor) का उपयोग शुरू कर सकते हैं।

{{#if (or section1 section2)}}  
...content  
{{/if}}

आप आगे जाने के लिए सब-डेप्रेशर को भी शामिल कर सकते हैं,

{{#if (or (eq section1 "section1") (eq section2 "section2") ) }}  
...content  
{{/if}}

2

फिर भी एक सहायक सहायक के लिए एक और कुटिल समाधान:

'?:' ( condition, first, second ) {
  return condition ? first : second;
}

<span>{{?: fooExists 'found it' 'nope, sorry'}}</span>

या एक साधारण मोटे सहायक:

'??' ( first, second ) {
  return first ? first : second;
}

<span>{{?? foo bar}}</span>

चूंकि इन पात्रों का हैंडलबार्स मार्कअप में कोई विशेष अर्थ नहीं है, इसलिए आप उन्हें हेल्पर नामों के लिए उपयोग करने के लिए स्वतंत्र हैं।


1

मुझे कॉफ़ीस्क्रिप्ट के साथ बनाया गया एक एनपीएम पैकेज मिला है जिसमें हैंडलबार्स के लिए बहुत सारे उपयोगी सहायक हैं। निम्नलिखित URL में दस्तावेज़ीकरण पर एक नज़र डालें:

https://npmjs.org/package/handlebars-helpers

आप wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgzउन्हें डाउनलोड करने और पैकेज की सामग्री को देखने के लिए एक कर सकते हैं ।

आप चीजों की तरह {{#is number 5}}या करने के लिए परेशान हो जाएगा{{formatDate date "%m/%d/%Y"}}


1

यदि आप केवल यह जांचना चाहते हैं कि क्या एक या दूसरा तत्व मौजूद है तो आप इस कस्टम हेल्पर का उपयोग कर सकते हैं

Handlebars.registerHelper('if_or', function(elem1, elem2, options) {
  if (Handlebars.Utils.isEmpty(elem1) && Handlebars.Utils.isEmpty(elem2)) {
    return options.inverse(this);
  } else {
    return options.fn(this);
  }
});

इस तरह

{{#if_or elem1 elem2}}
  {{elem1}} or {{elem2}} are present
{{else}}
  not present
{{/if_or}}

यदि आपको फ़ंक्शन रिटर्न मानों की तुलना करने के लिए "या" करने में सक्षम होना चाहिए, तो मैं एक और संपत्ति जोड़ना चाहूंगा जो वांछित परिणाम देता है।

सभी के बाद टेम्पलेट तर्कहीन होना चाहिए!



1

बस इस पोस्ट पर गूगल सर्च से आया कि कैसे एक स्ट्रिंग दूसरे स्ट्रिंग के बराबर होती है।

मैं NodeJS सर्वर-साइड में HandlebarsJS का उपयोग करता हूं, लेकिन मैं इसे पार्स करने के लिए HandlebarsJS के ब्राउज़र संस्करण का उपयोग करके फ्रंट-एंड पर समान टेम्प्लेट फ़ाइलों का भी उपयोग करता हूं। इसका मतलब यह था कि अगर मैं एक कस्टम सहायक चाहता था, तो मुझे इसे 2 अलग-अलग जगहों पर परिभाषित करना होगा, या प्रश्न में ऑब्जेक्ट को एक फ़ंक्शन असाइन करना होगा - बहुत अधिक प्रयास !!

जो लोग भूल जाते हैं वह यह है कि कुछ वस्तुओं में विरासत के कार्य होते हैं जिनका उपयोग मूंछ के खाके में किया जा सकता है। एक स्ट्रिंग के मामले में:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match

An Array containing the entire match result and any parentheses-captured matched results; null if there were no matches.

हम इस पद्धति का उपयोग करके या nullतो मिलान कर सकते हैं, या यदि कोई मिलान नहीं मिला। यह एकदम सही है, क्योंकि HandlebarsJS प्रलेखन http://handlebarsjs.com/builtin_helpers.html को देख रहा है

You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.

इसलिए...

{{#if your_string.match "what_youre_looking_for"}} 
String found :)
{{else}}
No match found :(
{{/if}}

अपडेट करें:

सभी ब्राउज़रों पर परीक्षण के बाद, यह फ़ायरफ़ॉक्स पर काम नहीं करता है । HandlebarsJS एक फ़ंक्शन कॉल के लिए अन्य तर्क पास करता है, जिसका अर्थ है कि जब String.prototype.match कहा जाता है, तो दूसरा तर्क (यानी ऊपर दिए गए दस्तावेज़ के अनुसार मैच फ़ंक्शन कॉल के लिए Regexp झंडे) पास किया जा रहा है। फ़ायरफ़ॉक्स इसे String.prototyp.match के एक पदावनत उपयोग के रूप में देखता है, और इसलिए टूट जाता है।

एक स्ट्रिंग स्ट्रिंग JS ऑब्जेक्ट के लिए एक नया कार्यात्मक प्रोटोटाइप घोषित करना है , और इसके बजाय इसका उपयोग करना है:

if(typeof String.includes !== 'function') {
    String.prototype.includes = function(str) {
        if(!(str instanceof RegExp))
            str = new RegExp((str+'').escapeRegExp(),'g');
        return str.test(this);
    }
}

सुनिश्चित करें कि यह JS कोड आपके Handlebars.compile () फ़ंक्शन को चलाने से पहले शामिल किया गया है, फिर अपने टेम्पलेट में ...

{{#your_string}}
    {{#if (includes "what_youre_looking_for")}} 
        String found :)
    {{else}}
        No match found :(
    {{/if}}
{{/your_string}}

फ़ायरफ़ॉक्स के लिए अद्यतन, यह वही है जो मैं वर्तमान में उपयोग कर रहा हूं
जॉन

1

यहां हमारे पास कई लॉजिकल && और || के लिए वेनिला हैंडलबार हैं (और या):

Handlebars.registerHelper("and",function() {
    var args = Array.prototype.slice.call(arguments);
    var options = args[args.length-1];

    for(var i=0; i<args.length-1; i++){
        if( !args[i] ){
            return options.inverse(this);
        }
    }

    return options.fn(this);
});


Handlebars.registerHelper("or",function() {
    var args = Array.prototype.slice.call(arguments);
    var options = args[args.length-1];

    for(var i=0; i<args.length-1; i++){
        if( args[i] ){
            return options.fn(this);
        }
    }

    return options.inverse(this);
}

// Results
// {{#and foo bar sally bob}} yup {{else}} nope {{/and}} // yup
// {{#or foo bar "" sally bob}} yup {{else}} nope {{/or}} // yup

// {{#and foo bar "" sally bob}} yup {{else}} nope {{/and}} // nope
// {{#or "" "" "" "" ""}} yup {{else}} nope {{/or}} // nope

यकीन नहीं है कि अगर यह "उपयोग करने के लिए" सुरक्षित है "और" और "या" ... शायद "op_and" और "op_or" जैसी किसी चीज़ में बदल जाए?


1

और / या के लिए सही समाधान

Handlebars.registerHelper('and', function () {
    // Get function args and remove last one (function name)
    return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);
});
Handlebars.registerHelper('or', function () {
    // Get function args and remove last one (function name)
    return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);
}); 

फिर निम्नानुसार कॉल करें

{{#if (or (eq questionType 'STARTTIME') (eq questionType 'ENDTIME') (..) ) }}

BTW: ध्यान दें कि यहां दिया गया समाधान गलत है, वह अंतिम तर्क को नहीं घटा रहा है जो कि फ़ंक्शन का नाम है। https://stackoverflow.com/a/31632215/1005607

उनका मूल और / या तर्क की पूरी सूची पर आधारित था

   and: function () {
        return Array.prototype.slice.call(arguments).every(Boolean);
    },
    or: function () {
        return Array.prototype.slice.call(arguments).some(Boolean);
    }

क्या कोई उस उत्तर को बदल सकता है? मैंने सिर्फ 86 लोगों द्वारा सुझाए गए उत्तर में कुछ तय करने की कोशिश में एक घंटा बर्बाद किया। फिक्स अंतिम तर्क को फ़िल्टर करना है जो फ़ंक्शन नाम है।Array.prototype.slice.call(arguments, 0, arguments.length - 1)


0

इन 2 गाइड के बाद एक तरह से करने के लिए जाने-उन-परिभाषित-कस्टम निर्मित बाध्य-अगर-बयानों और कस्टम बाध्य सहायकों मैं पर इस पोस्ट में अपने साझा किए गए विचारों को समायोजित करने में सक्षम था stackoverflow मानक # के बजाय इसका उपयोग करने के लिए अगर बयान। यह वहाँ # # टॉस करने से अधिक सुरक्षित होना चाहिए।

उस gist में कस्टम बाउंड हेल्पर्स बकाया हैं।

<li>
    <a href="{{unbound view.varProductSocialBlog}}">
        {{#if-equal view.showDiv "true"}}<div>{{/if-equal}}<i class="fa fa-rss-square"></i>{{#if-equal view.showDiv "true"}}</div>{{/if-equal}}
        {{#if-equal view.showTitle "true"}}Blog{{/if-equal}}
    </a>
</li>

मैं एम्बर क्लि का उपयोग कर रहा हूं अपने एम्बर एप्लिकेशन के निर्माण के प्रोजेक्ट ।

इस पोस्ट के समय वर्तमान सेटअप:

DEBUG: -------------------------------
DEBUG: Ember      : 1.5.1
DEBUG: Ember Data : 1.0.0-beta.7+canary.b45e23ba
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery     : 2.1.1
DEBUG: -------------------------------

0

Ember.js में यदि आप हेल्पर को ब्लॉक हेल्पर में इनलाइन का उपयोग कर सकते हैं । यह ||तार्किक ऑपरेटर की जगह ले सकता है , उदाहरण के लिए:

{{#if (if firstCondition firstCondition secondCondition)}}
  (firstCondition || (or) secondCondition) === true
{{/if}}

0

आप इसे नीचे दिखाए गए जैसे तार्किक ऑपरेटर का उपयोग करके कर सकते हैं:

{{#if (or(eq firstValue 'String_to_compare_value') (eq secondValue 'String_to_compare_value'))}}business logic goes here{{/if}}

{{#if (and(eq firstValue 'String_to_compare_value') (eq secondValue 'String_to_compare_value'))}}business logic goes here{{/if}}

बंद करने से पहले यदि आप अपने व्यापार तर्क लिख सकते हैं


0

आप निम्नलिखित कोड का उपयोग कर सकते हैं:

{{#if selection1}}
    doSomething1
{{else}}
   {{#if selection2}}
       doSomething2
   {{/if}}
{{/if}}

कृपया अपने विचारों और प्रक्रिया के बारे में अधिक बताएं, लोगों को आपके समाधान को समझना बहुत मुश्किल हो सकता है यदि वे संदर्भ को नहीं जानते हैं या भाषा के लिए नए हैं।
मारह

-1

यहाँ मैं एम्बर 1.10 और एम्बर-क्ली 2.0 का उपयोग कर रहा हूं।

// app/helpers/js-x.js
export default Ember.HTMLBars.makeBoundHelper(function (params) {
  var paramNames = params.slice(1).map(function(val, idx) { return "p" + idx; });
  var func = Function.apply(this, paramNames.concat("return " + params[0] + ";"))
  return func.apply(params[1] === undefined ? this : params[1], params.slice(1));
});

फिर आप इसे इस तरह से अपने टेम्पलेट में उपयोग कर सकते हैं:

// used as sub-expression
{{#each item in model}}
  {{#if (js-x "this.section1 || this.section2" item)}}
  {{/if}}
{{/each}}

// used normally
{{js-x "p0 || p1" model.name model.offer.name}}

कहाँ अभिव्यक्ति के तर्कों के रूप में पारित कर रहे हैं p0, p1, p2आदि और p0भी रूप में संदर्भित किया जा सकता this

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