Bir gidondaki mantıksal operatör. {{#İf}} koşullu


479

Gidon JS'de mantıksal işleçleri standart gidonlara. Koşullu operatöre dahil etmenin bir yolu var mı? Bunun gibi bir şey:

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

Kendi yardımcımı yazabileceğimi biliyorum, ama önce tekerleği yeniden keşfetmediğimden emin olmak istiyorum.

Yanıtlar:


518

Bu, bir blok yardımcı ile 'aldatarak' mümkündür. Bu muhtemelen Gidon geliştiren insanların İdeolojisine aykırıdır.

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

Daha sonra şablondaki yardımcıyı şöyle çağırabilirsiniz

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

54
Bu, Gidonların / Bıyığın mantıksız doğasına aykırıdır, ancak yine de kesinlikle yararlıdır, teşekkürler!
Bala Clark

6
Bunun yalnızca ilişkili özelliklerle (okuma, Ember bağlamaları) çalışmadığını unutmayın. Değişmez değerlerle iyidir, ancak model özelliklerini (Ember 1.0.0-rc.8 ve Gidon 1.0.0 ile test edilmiştir) çözmez ve registerBoundHelperGidon sözdizimi ile baş edemez. Çözüm, özel bir görünüm oluşturmaktır: stackoverflow.com/questions/18005111/…
Warren Seine

28
@BalaClark gerçekten mantıklı değil mi? Demek istediğim hala "if" ifadelerine sahip - sadece kasıtlı olarak sakat oldukları için felsefeyi değiştirmiyor.
phreakhead

111
Geliştiricilerin neden kendilerini sakatlamaktan hoşlandıklarını hiç anlamadım.
StackOverflowed

36
AND / OR'nin neden Gidonların bir parçası olamayacağını anlamıyorum. Zaten mantıksız doğaya aykırı değildir çünkü zaten IF, UNLESS ve EACH vardır ... mantıksız için çok fazla
Asaf

445

Çözümü bir adım daha ileri götürmek. Bu karşılaştırma operatörünü ekler.

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);
    }
});

Şunun gibi bir şablonda kullanın:

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

Coffee Script sürümü

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
unutma '||'ve '&&'. Bu vakaları ekledim ve çok faydalılar.
Jason

20
Gidonları bir noob olmak, net olmayan bir şey, işleci bir dize olarak geçirmeniz gerektiğidir, aksi takdirde derleyici şablonunuzu belirlerken hata verir. {{#ifCond true '==' false}}
Joe Holloway

2
Nesne öznitelikleri için değerlendirilmeyecek değerleri buldum. Aşağıdakileri eklemek yardımcı olur v1 = Ember.Handlebars.get(this, v1, options) v2 = Ember.Handlebars.get(this, v2, options)
ZX12R

4
ama eğer v1 ve v2 de bir koşul varsa nasıl kullanabilirim? örneğin: if (değer == "a" || değer == "b")
Krishna

3
Bununla başka bir şey yapabilir misin?
jbyrd

160

Gidon yuvalanmış işlemleri destekler. Bu, mantığımızı biraz farklı yazarsak çok fazla esneklik (ve daha temiz kod) sağlar.

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

Aslında, her türlü mantığı ekleyebiliriz:

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

Şu yardımcıları kaydetmeniz yeterlidir:

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 kadar bu mümkün olmadığını unutmayın. Ayrıca, isterseniz bu yardımcılar bir Ember CLI eklentisi olarak gelir: github.com/jmurphyau/ember-truth-helpers .
stephen.hanson

1
Bu şekilde, hiçbir optionsyürütme olmadan ifyöntemle tutmak daha iyi ve test etmek daha kolaydır. Teşekkürler!
Washington Botelho

25
Lisp'i gidonlara yerleştirmiş gibi görünüyoruz.
jdunning

8
Sizin andve oryardımcılarınız sadece 2 parametre ile çalışır, bu istediğiniz değildir. İkiden fazla parametreyi desteklemek için andhem oryardımcıları hem de yardımcıları yeniden çalışmayı başardım . İçin bu tek astar kullanın and: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);ve bu tek astar kullanın or: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);.
Luke

3
Bir biraz daha gelişmiş versiyonu her operatöre üzerinde birçok parametreyi alabilir.
Nate

87

kenarda yaşayanlarınız için bir çentik almak.

gist : https://gist.github.com/akhoury/9118682 Gösteri : Aşağıdaki kod snippet'i

Gidon Yardımcısı: {{#xif EXPRESSION}} {{else}} {{/xif}}

herhangi bir ifadeyle bir IF ifadesi yürütmek için bir yardımcı

  1. EXPRESSION düzgün bir şekilde kaçan bir String
  2. Evet İHTİYACINIZ düzgün dize hazır ya da sadece alternatif tek ve çift tırnak kaçmak için
  3. herhangi bir global işleve veya özelliğe erişebilirsiniz. encodeURIComponent(property)
  4. Bu örnek, bu bağlamı gidonlarınıza geçirdiğinizi varsayar template( {name: 'Sam', age: '20' } ), uyarı agebir string, bu nedenle parseInt()daha sonra bu yayında demo yapabilirim

Kullanımı:

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

Çıktı

<p>
  BOOM
</p>

JavaScript: (başka bir yardımcıya bağlıdır - okumaya devam edin)

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

Gidon Yardımcısı: {{x EXPRESSION}}

Javascript ifadeleri yürütmek için bir yardımcı

  1. EXPRESSION düzgün bir şekilde kaçan bir String
  2. Evet İHTİYACINIZ düzgün dize hazır ya da sadece alternatif tek ve çift tırnak kaçmak için
  3. herhangi bir global işleve veya özelliğe erişebilirsiniz. parseInt(property)
  4. Bu örnek size gidonlara bu bağlamda geçti varsayar template( {name: 'Sam', age: '20' } ), agebir olan stringdemo amaç için, bu olabilir şey ..

Kullanımı:

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

Çıktı:

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

JavaScript:

Bu biraz büyük görünüyor çünkü sözdizimini genişlettim ve netlik amacıyla neredeyse her satıra yorum yaptım

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

üst düzey kapsama erişmek istiyorsanız, bu biraz farklıdır, ifade tüm argümanların birleşimidir, kullanım: diyelim bağlam verileri şöyle görünür:

// 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}}

JavaScript:

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
Bu harika. Gidon size ne yapacağınızı söyleyemez :)
lemiant

1
:) teşekkürler, biraz daha fazla güzellik eklemek için biraz gist güncelledim (doğrudan bu SO soru ile ilgili değil - ama bir gidon şablon içinde ne istediğinizi yapma ruhuyla) Ancak, sınırlamalara dikkat etmeliyim, ifade içinde "üst kapsam düzeylerine" erişmenin bir yolunu bulamadım, her bir kapsamda olduğunuzu söyleyin, {{#each}} ... {{xif ' ../name === this.name' }} {{/each}}... ama hala araştırıyorum ..
bentael

1
"üst kapsam erişimi" için bir çözüm bulundu, ancak yeni bir yardımcı kullanarak, güncellenmiş yanıt, {{z ...}}yardımcı
bentael

BOOM ! Harika, şimdi kısmi teşekkürlerimi içinde gerçek durum yapabilirim !
AncAinu

1
@rickysullivan bunun yerine deneyin eval(expression);: eval('(function(){try{return ' + expression + ';}catch(e){}})();');- Bu çirkin olduğunu biliyorum, ama bunu yapmak için güvenli bir yol düşünemiyorum - lütfen bu yürütmek için çok "hızlı" olmadığını unutmayın, bunu yapmak olmaz büyük yineleme.
bentael

33

Bir yardımcı fonksiyon yazmadan bunu yapmanın basit bir yolu var ... Şablon içinde tamamen yapılabilir.

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

Düzenleme: Tam tersine bunu yapabilir veya şunları yapabilirsiniz:

{{#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}}

Düzenleme / Not: Gidon web sitesinden: handlebarsjs.com burada sahte değerler şunlardır:

Koşullu olarak bir blok oluşturmak için if yardımcısını kullanabilirsiniz. Argümanı false, undefined, null, "" veya [] (bir "falsy" değeri) döndürürse, herhangi bir 'cond' (cond1 veya cond2 gibi) true olarak sayılmaz.


9
Gerçekten değil, iki değeri karşılaştırmazsınız, her ikisinin de var olduğundan emin olursunuz, farklıdır.
Cyril N.

3
Aslında javascript'in web sitesinden olduğu gibi değerlendirir: "Koşullu olarak bir blok oluşturmak için if yardımcısını kullanabilirsiniz. Argümanı false, undefined, null" "veya [] (bir" falsy "değeri) döndürürse, Gidon blokları oluşturmaz. "
Jono

1
Haklısın, öncelikle testin iki değeri karşılaştırmak olduğunu düşündüm, her ikisinin de testini değil. Benim hatam, üzgünüm.
Cyril N.Eylül

4
Bu düzgün çalışmıyor. Cond1 doğruysa ve con2 yanlışsa, hiçbir şey yazdırılmaz.
Tessa Lau

1
Hey @TessaLau, sanırım nereden geldiğini görüyorum. Bununla birlikte, bir kontrol akışı çizerseniz, ilk satırda kontrol akışını bu koşula taşır.
Jono

19

Burada yayınlanan tüm cevaplar ile ilgili bir sorun, ilişkili özelliklerle, yani ilgili özellikler değiştiğinde if koşulunun yeniden değerlendirilmemesi ile çalışmıyor olmasıdır. İşte, destekleyicileri destekleyen yardımcının biraz daha gelişmiş bir sürümü. Normal Ember yardımcısını uygulamak için de kullanılan Ember kaynağından bağlama işlevini kullanır #if.

Bu, en pratik amaçlar için yeterince iyi olduğunu düşündüğüm, sağ taraftaki bir sabitle karşılaştırıldığında, sol taraftaki tek bağlı bir özellikle sınırlıdır. Basit bir karşılaştırmadan daha gelişmiş bir şeye ihtiyacınız varsa, belki de bazı hesaplanmış özellikleri bildirmeye ve #ifbunun yerine normal yardımcıyı kullanmaya başlamak iyi olur .

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

Bu şekilde kullanabilirsiniz:

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

Ember kullanıyorsanız uygun cevap budur. Bahsettiğiniz diğer çözümler sadece değer yerine anahtarı geçecektir. BTW bunun için teşekkürler, kafamı sarmak için birkaç saat geçirdim.
J Lee

2
HTMLBars / Ember 1.10 ile bu çalışmayı bilen var mı? Ember.Handlebars.bind artık mevcut değil.
Linda

Başlangıçta registerBoundHelper kullandım ama daha sonra durumu değiştiğinde başka bir değere ve geri değişmez .. Bu yöntem değiştirmek için kor ile çalışır :) Çok daha fazla oy olmalı
Matt Vukomanovic

13

Temel olarak herhangi bir ikili operatörle çalışan geliştirilmiş çözüm (en azından sayılar, dizeler eval ile iyi çalışmaz, KULLANICI GİRİŞLERİ İLE TANIMLANMAMIŞ BİR OPERATÖR KULLANILIRSA MÜMKÜN SENARYO ENJEKSİYONUNA BAKIN):

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);
    }
});

bunu bir şablonda nasıl kullanırsınız? özellikle options.fn parçası?
qodeninja

{{ifCond val1 '||' val2}} true {{else}} false {{/ if}}, doğruysa options.fn (true, ifCond yantümcesi) döndürür, aksi halde yanlışsa options.inverse (false, else yan tümcesi) döndürür.
Nick Kitto

1
Komut dosyası enjeksiyonu hakkında belirtilen uyarı nedeniyle, bu yardımcıyı kullanmamanızı şiddetle tavsiye ederim. Büyük bir kod tabanında bu kolayca kötü bir güvenlik sorunu sorumlu olabilir
Jordan Sitkin

8

Birden fazla koşulu kontrol etmek istiyorsanız bir çözüm:

/* 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);
  });

Kullanımı:

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

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

7

İşte kullandığım blok yardımcısına bir bağlantı: karşılaştırma blok yardımcısı . Tüm standart operatörleri destekler ve aşağıda gösterildiği gibi kod yazmanıza izin verir. Gerçekten çok kullanışlı.

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

1
Bu kazanan oy olmalı. Yerli ve amaçlı. Neredeyse her seferinde yeni bir yardımcı yazıyorsanız, onu düşünüyor olduğunuzu görüyorum.
augurone

2
@augurone bu yerli bir yardımcı değil. Bağlantıyı izlerseniz, bunun özel olarak tanımlanmış bir yardımcı olduğunu görürsünüz.
gfullam

@gfullam haklısın, montajda doğal olarak bu yardımcıyı içeren gidon kullanıyordum. Benim hatam.
augurone

4

Jim'in cevabına benzer, ancak biraz yaratıcılık kullanarak böyle bir şey de yapabiliriz:

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 );
} );

Sonra kullanmak için şöyle bir şey elde ederiz:

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

Daha iyi performans için nesneyi işlev dışına taşımanızı öneririm, ancak aksi takdirde "ve" ve "veya" dahil olmak üzere istediğiniz karşılaştırma işlevini ekleyebilirsiniz.


3

Diğer bir seçenek de işlev adını kullanmaktır #if. #ifParametre işlevi ise algılar ve daha sonra ise onu arayıp truthyness kontrolü için onun dönüşünü kullanacaktır. MyFunction altında geçerli bağlam olarak alır this.

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

Bağlama bir fonksiyon eklemeniz gerekir mi? Kodun bir bağlamdan yürütülmesi, kodun kaynağı bilinmiyor olabileceğinden bir güvenlik deliğidir. Bu bir XSS saldırısı için kullanılabilir.
T Nguyen

Evet, bağlama fonksiyon eklemeniz gerekiyor. Kötü tasarlanmış bir web sitesinde, evet, bu güvenlik deliği olabilir. Ama bu durumda, başkaları da olurdu.
Shital Shah

Bu tercih edilen yoldur .. TY.
elad.chen

3

Ne yazık ki bu çözümlerin hiçbiri "VEYA" operatörü "cond1 || cond2" sorununu çözmemektedir.

  1. İlk değerin doğru olup olmadığını kontrol edin
  2. "^" (Veya) kullanın ve koşul 2'nin doğru olup olmadığını kontrol edin

    {{#if cond1}} EYLEM YAPIN {{^}} {{#if cond2}} EYLEM YAPIN {{/ if}} {{/ if}}

KURU kurallara aykırıdır. Öyleyse neden daha az dağınık hale getirmek için kısmi kullanmıyorsunuz?

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

3

Şablonunuzda gerçekleştirmek için çok sayıda çeşitli karşılaştırmanın olduğu durumlar için neden bir yardımcı oluşturmak istediğinizi anlayabiliyorum, ancak nispeten az sayıda karşılaştırma (hatta beni bu sayfaya getiren şey) ilk olarak), muhtemelen görüntüleme oluşturma işlevi çağrınızda yeni bir gidon değişkeni tanımlamak daha kolay olurdu, örneğin:

Renderde gidonlara geç:

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

ve ardından gidon şablonunuzda:

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

Basitlik uğruna bundan bahsediyorum ve aynı zamanda Gidonların mantıksız doğasına hala uyurken hızlı ve yararlı olabilecek bir cevap.


3

Aşağıdaki komutu çalıştırarak Ember Truth Helpers eklentisini yükleyin

kor yüklemek ember-truth-helpers

mantıksal işleçlerin çoğunu kullanmaya başlayabilirsiniz (eq, not-eq, not, ve, gt, gte, lt, lte, xor).

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

Daha ileri gitmek için alt ifadeyi bile ekleyebilirsiniz,

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

2

Üçlü bir yardımcı için başka bir çarpık çözüm:

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

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

Veya basit bir birleşim yardımcısı:

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

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

Bu karakterlerin gidon işaretlemesinde özel bir anlamı olmadığı için bunları yardımcı isimler için kullanabilirsiniz.


1

Gidon için inanılmaz faydalı yardımcıları olan CoffeeScript ile yapılmış bir npm paketi buldum. Aşağıdaki URL'deki dokümanlara göz atın:

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

Yapabilirsin wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgz indirmek ve paketin içeriğini görmek için .

Sen gibi şeyler yapmak Engelsiz edilecek {{#is number 5}}veya{{formatDate date "%m/%d/%Y"}}


1

eğer sadece bir elemanın veya diğer elemanın mevcut olup olmadığını kontrol etmek istiyorsanız bu özel yardımcıyı kullanabilirsiniz

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);
  }
});

bunun gibi

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

işlev döndürme değerlerini karşılaştırmak için "veya" işaretine sahip olmanız gerekiyorsa , istenen sonucu döndüren başka bir özellik eklemeyi tercih ederim.

Sonuçta şablonlar mantıksız olmalı!



1

Bir dizenin başka bir dizeye eşit olup olmadığını nasıl kontrol edeceğiniz konusunda bir Google aramasından bu gönderiye yeni geldim.

NodeJS sunucu tarafında HandlebarsJS kullanıyorum, ancak ayrıştırmak için HandlebarsJS'nin tarayıcı sürümünü kullanarak aynı şablon dosyalarını ön uçta da kullanıyorum. Bu, özel bir yardımcı istersem, 2 ayrı yerde tanımlamak veya söz konusu nesneye bir işlev atamak zorunda olduğum anlamına geliyordu - çok fazla çaba!

İnsanların unuttuğu şey, bazı nesnelerin bıyık şablonunda kullanılabilecek devralma işlevlerine sahip olmasıdır. Bir dize durumunda:

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.

Bir eşleşme dizisi döndürmek veya nulleşleşme bulunmadıysa bu yöntemi kullanabiliriz . Bu mükemmel, çünkü Gidon JS belgelerine bakın 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.

Yani...

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

GÜNCELLEME:

Tüm tarayıcılarda test ettikten sonra, bu Firefox'ta çalışmaz . HandlebarsJS işlev çağrısına başka bağımsız değişkenler iletir, yani String.prototype.match çağrıldığında ikinci bağımsız değişken (yani yukarıdaki belgelere göre eşleşme işlevi çağrısı için Regexp bayrakları) geçirilmiş gibi görünür. Firefox bunu String.prototype.match'in kullanımdan kaldırılmış bir kullanımı olarak görür ve bu nedenle sonlar.

Geçici bir çözüm, String JS nesnesi için yeni bir işlevsel prototip bildirmek ve bunun yerine bunu kullanmaktır:

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

Handlebars.compile () işlevinizi çalıştırmadan önce şablonunuzda bu JS kodunun eklendiğinden emin olun ...

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

Firefox için güncellendi, şu anda kullanıyorum
Jon

1

Burada çoklu mantık ve & ve || için vanilya gidonlarımız var (ve veya):

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

"Ve" ve "veya" ... kullanmak için "güvenli" olup olmadığından emin değilsiniz "op_and" ve "op_or" gibi bir şeye değişebilir mi?


1

AND / OR için Doğru Çözüm

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);
}); 

Sonra aşağıdaki şekilde arayın

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

BTW: Burada verilen çözümün yanlış olduğunu, işlev adı olan son argümanı çıkarmadığını unutmayın. https://stackoverflow.com/a/31632215/1005607

Orijinal VE / VEYA argümanların tam listesine dayanıyordu

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

Birisi bu cevabı değiştirebilir mi? Sadece 86 kişi tarafından önerilen bir cevapta bir şeyi düzeltmeye çalışırken bir saat harcadım. Düzeltme, işlev adı olan son bağımsız değişkeni filtrelemektir .Array.prototype.slice.call(arguments, 0, arguments.length - 1)


0

Bu 2 kılavuzdan sonra kullanıcılara tanımlanmasına izin ver-özel-made-bound-if-ifadeleri ve özel bağlı yardımcıları izleyerek stackoverflow'daki bu yayında paylaşılan görünümlerimi standart # yerine kullanmak üzere ayarlayabildim if ifadesi. Bu, içine bir #if atmaktan daha güvenli olmalıdır.

O gistteki özel bağlı yardımcılar olağanüstü.

<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>

Kor cli kullanıyorumKor uygulamasını oluşturmak projesini .

Bu gönderinin yapıldığı tarihte geçerli kurulum:

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'de , eğer blok helper ise inline if helper komutunu kullanabilirsiniz . ||Mantıksal operatörün yerini alabilir , örneğin:

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

0

Bunu, aşağıda gösterildiği gibi mantıksal işleci kullanarak kolayca yapabilirsiniz:

{{#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}}

Kapatmadan önce iş mantığınızı yazabiliyorsanız


0

Aşağıdaki kodu kullanabilirsiniz:

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

Lütfen düşünceleriniz ve süreciniz hakkında daha fazla açıklama yapın, insanların bağlamı bilmiyorlarsa veya dil için yeniyse çözümünüzü anlamaları çok zor olabilir.
mrhn

-1

İşte ember 1.10 ve ember-cli 2.0 için kullandığım bir yaklaşım.

// 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));
});

Ardından, şablonlarınızda şu şekilde kullanabilirsiniz:

// 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}}

İfade argümanlar olarak iletilen yerlerde p0, p1, p2vb ve p0aynı zamanda başvurulabilir this.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.