Operator logis dalam kondisi setang {{#if}}


479

Apakah ada cara di setang JS untuk memasukkan operator logis ke dalam operator kondisional setang standar? Sesuatu seperti ini:

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

Saya tahu saya bisa menulis pembantu saya sendiri, tetapi pertama-tama saya ingin memastikan saya tidak menciptakan kembali roda.

Jawaban:


519

Ini dimungkinkan dengan 'curang' dengan pembantu blok. Ini mungkin bertentangan dengan Ideologi orang-orang yang mengembangkan Setang.

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

Anda kemudian dapat memanggil helper dalam templat seperti ini

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

54
Ini memang bertentangan dengan sifat Setang / Kumis yang tidak masuk akal, tapi tetap saja bermanfaat, terima kasih!
Bala Clark

6
Perhatikan bahwa ini tidak berfungsi dengan properti terikat (baca, Ember bindings). Tidak masalah dengan nilai literal, tetapi tidak menyelesaikan properti model (diuji dengan Ember 1.0.0-rc.8 dan Handlebars 1.0.0), dan registerBoundHelpertidak dapat menangani sintaks Handlebars. Solusinya adalah membuat tampilan khusus: stackoverflow.com/questions/18005111/…
Warren Seine

28
@BalaClark, apakah ini benar-benar tidak masuk akal? Maksud saya masih memiliki pernyataan "jika" - hanya karena mereka sengaja dilumpuhkan tidak mengubah filosofi.
phreakhead

111
Saya tidak pernah mengerti mengapa pengembang suka cacat sendiri.
StackOverflowed

36
Saya tidak mengerti mengapa DAN / ATAU tidak bisa menjadi bagian dari Setang. Itu tidak bertentangan dengan sifat tanpa logika karena sudah ada JIKA, KECUALI, dan SETIAP ... begitu banyak untuk tanpa logika
Asaf

445

Mengambil solusi satu langkah lebih jauh. Ini menambahkan operator perbandingan.

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

Gunakan dalam template seperti ini:

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

Versi Script kopi

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
jangan lupakan '||'dan '&&'. Saya menambahkan kasus-kasus ini dan sangat berguna.
Jason

20
Menjadi noob untuk setang satu hal yang tidak jelas adalah bahwa Anda harus melewati operator sebagai string atau jika tidak kompiler akan kesalahan saat tokenizing template Anda. {{#ifCond true '==' false}}
Joe Holloway

2
Saya menemukan nilai tidak akan dievaluasi untuk atribut objek. Menambahkan bantuan berikut v1 = Ember.Handlebars.get(this, v1, options) v2 = Ember.Handlebars.get(this, v2, options)
ZX12R

4
tetapi jika v1 dan v2 juga satu syarat maka bagaimana saya bisa menggunakan? misalnya: if (value == "a" || value == "b")
Krishna

3
Bisakah Anda melakukan yang lain jika dengan ini?
jbyrd

160

Setang mendukung operasi bersarang. Ini memberikan banyak fleksibilitas (dan kode pembersih) jika kita menulis logika kita sedikit berbeda.

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

Faktanya, kita dapat menambahkan semua jenis logika:

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

Cukup daftarkan pembantu ini:

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
Perhatikan bahwa ini tidak mungkin sampai HTMLBars di Ember 1.10. Juga, para pembantu itu datang sebagai addon Ember CLI jika Anda lebih suka: github.com/jmurphyau/ember-truth-helpers .
stephen.hanson

1
Dengan cara ini, tanpa optionseksekusi lebih baik menggunakan ifmetode dan lebih mudah untuk diuji. Terima kasih!
Washington Botelho

25
Kami tampaknya telah membangun Lisp menjadi Setang.
Mengejek

8
Anda anddan orpembantu hanya bekerja dengan 2 parameter, yang bukan yang Anda inginkan. Saya berhasil mengolah anddan ormembantu untuk mendukung lebih dari dua parameter. Gunakan ini satu-liner untuk and: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);dan menggunakan ini satu-liner untuk or: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);.
Luke

3
Versi yang sedikit lebih maju yang dapat mengambil banyak parameter pada setiap operator.
Nate

87

mengambil yang satu ini takik, bagi Anda yang hidup di tepi.

inti : https://gist.github.com/akhoury/9118682 Demo : Cuplikan kode di bawah ini

Setang Helper: {{#xif EXPRESSION}} {{else}} {{/xif}}

pembantu untuk mengeksekusi pernyataan IF dengan ekspresi apa pun

  1. EXPRESSION adalah String yang lolos dengan benar
  2. Ya, Anda PERLU untuk melarikan diri dari string literal atau hanya kutip tunggal dan ganda bergantian
  3. Anda dapat mengakses fungsi global atau properti yaitu encodeURIComponent(property)
  4. contoh ini mengasumsikan Anda meneruskan konteks ini ke setang Anda template( {name: 'Sam', age: '20' } ), pemberitahuan ageadalah string, hanya agar saya dapat melakukan demo parseInt()nanti di posting ini

Pemakaian:

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

Keluaran

<p>
  BOOM
</p>

JavaScript: (tergantung pada helper-terus membaca)

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

Setang Helper: {{x EXPRESSION}}

Seorang penolong untuk mengeksekusi ekspresi javascript

  1. EXPRESSION adalah String yang lolos dengan benar
  2. Ya, Anda PERLU untuk melarikan diri dari string literal atau hanya kutip tunggal dan ganda bergantian
  3. Anda dapat mengakses fungsi global atau properti yaitu parseInt(property)
  4. contoh ini mengasumsikan Anda meneruskan konteks ini ke setang Anda template( {name: 'Sam', age: '20' } ), ageadalah stringuntuk tujuan demo, bisa apa saja ..

Pemakaian:

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

Keluaran:

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

JavaScript:

Ini terlihat agak besar karena saya memperluas sintaksis dan mengomentari hampir setiap baris untuk tujuan kejelasan

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

jika Anda ingin mengakses ruang lingkup tingkat atas, yang ini sedikit berbeda, ekspresi adalah GABUNG dari semua argumen, penggunaan: katakanlah data konteks terlihat seperti ini:

// 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
Ini bagus. Setang tidak dapat memberi tahu Anda apa yang harus dilakukan :)
lemiant

1
:) terima kasih, saya memperbarui intinya sedikit untuk menambahkan beberapa barang lagi (tidak terkait langsung dengan pertanyaan SO ini - tetapi dengan semangat melakukan apa yang Anda inginkan di dalam template setang) Namun, Anda harus berhati-hati terhadap batasannya, saya harus berhati-hati terhadap keterbatasannya, saya belum dapat menemukan cara untuk mengakses "tingkat ruang lingkup atas" dari dalam ekspresi, katakan Anda berada dalam ruang lingkup masing-masing, {{#each}} ... {{xif ' ../name === this.name' }} {{/each}}... tapi saya masih menyelidiki ..
bentael

1
menemukan solusi untuk "akses ruang lingkup atas" tetapi menggunakan penolong baru, lihat jawaban yang diperbarui, {{z ...}}penolong
bentael

BOOM! Luar biasa, sekarang saya bisa melakukan kondisi nyata di dalam sebagian terima kasih saya !
AncAinu

1
@rickysullivan coba ganti eval(expression);dengan Anda : eval('(function(){try{return ' + expression + ';}catch(e){}})();');- saya tahu ini semakin jelek, tetapi tidak bisa memikirkan cara yang aman untuk melakukan ini - harap perhatikan bahwa ini tidak terlalu "cepat" untuk dieksekusi, saya tidak akan melakukan ini dalam iterasi besar.
bentael

33

Ada cara sederhana untuk melakukan ini tanpa menulis fungsi pembantu ... Itu bisa dilakukan dalam template sepenuhnya.

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

Sunting: Sebaliknya Anda dapat melakukan atau dengan melakukan ini:

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

Edit / Catatan: Dari situs web stang: handlebarsjs.com berikut adalah nilai-nilai palsu:

Anda dapat menggunakan pembantu jika untuk membuat blok secara kondisional. Jika argumennya mengembalikan nilai false, undefined, null, "" atau [] (a "falsy"), maka setiap 'cond' (seperti cond1 atau cond2) tidak akan dihitung sebagai benar.


9
Tidak juga, Anda tidak membandingkan dua nilai, Anda hanya memastikan keduanya ada, itu berbeda.
Cyril N.

3
Sebenarnya ia mengevaluasinya dengan cara yang sama seperti javascript, dari situs web: "Anda dapat menggunakan penolong if untuk membuat blok secara kondisional. Jika argumennya mengembalikan nilai false, undefined, null," "atau [] (a" falsy "), Setang tidak akan merender blokir. "
Jono

1
Anda benar, saya pertama kali berpikir tes itu untuk membandingkan dua nilai, bukan pengujian keduanya. Saya buruk, maaf
Cyril N.

4
Ini tidak berfungsi dengan benar. Jika cond1 benar dan con2 salah, tidak ada yang akan dicetak.
Tessa Lau

1
Hei @TessaLau, saya rasa saya tahu dari mana Anda berasal. Namun jika Anda menggambar aliran kontrol Anda akan melihat bahwa di baris pertama menggerakkan aliran kontrol ke kondisi itu.
Jono

19

Satu masalah dengan semua jawaban yang diposting di sini adalah bahwa mereka tidak bekerja dengan properti terikat, yaitu kondisi if tidak dievaluasi kembali ketika properti yang terlibat berubah. Berikut ini versi yang lebih maju dari binding binding pembantu. Ia menggunakan fungsi bind dari sumber Ember, yang juga digunakan untuk mengimplementasikan #ifpembantu Ember normal .

Yang ini terbatas pada properti terikat tunggal di sisi kiri, dibandingkan dengan konstan di sisi kanan, yang saya pikir cukup baik untuk tujuan praktis. Jika Anda membutuhkan sesuatu yang lebih maju daripada perbandingan sederhana, maka mungkin akan lebih baik untuk mulai mendeklarasikan beberapa properti yang dihitung dan menggunakan #ifpembantu normal sebagai gantinya.

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

Anda bisa menggunakannya seperti ini:

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

Ini adalah jawaban yang tepat jika Anda menggunakan Ember. Solusi lain seperti yang Anda sebutkan hanya akan meneruskan kunci alih-alih nilai. Terima kasih BTW untuk ini, menghabiskan beberapa jam membongkar kepalaku.
J Lee

2
Adakah yang mendapatkan ini berfungsi dengan HTMLBars / Ember 1.10? Ember.Handlebars.bind tampaknya tidak ada lagi.
Linda

Saya awalnya menggunakan registerBoundHelper awalnya tetapi kemudian ketika kondisi berubah itu tidak akan berubah ke nilai yang lain dan kembali .. Metode ini bekerja dengan bara untuk mengubah :) Ini harus memiliki lebih banyak suara
Matt Vukomanovic

13

Solusi yang ditingkatkan yang pada dasarnya bekerja dengan operator biner mana pun (setidaknya angka, string tidak bekerja dengan baik dengan eval, MENGAMBIL INJEKSI SCRIPT MUNGKIN JIKA MENGGUNAKAN OPERATOR NON DEFINISI DENGAN INPUT PENGGUNA):

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

bagaimana Anda menggunakan ini dalam templat? terutama bagian options.fn?
qodeninja

{{ifCond val1 '||' val2}} true {{else}} false {{/ if}} ia mengembalikan options.fn (true, klausa ifCond) jika itu benar, jika tidak maka mengembalikan options.inverse (false, klausa lain) jika salah.
Nick Kitto

1
Karena peringatan yang disebutkan tentang injeksi skrip, saya akan sangat menyarankan agar tidak menggunakan pembantu ini. Dalam basis kode besar ini dengan mudah dapat bertanggung jawab atas masalah keamanan yang buruk di telepon
Jordan Sitkin

8

Ini solusinya jika Anda ingin memeriksa beberapa kondisi:

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

Pemakaian:

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

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

7

Berikut tautan ke helper blok yang saya gunakan: pembanding blok helper . Ini mendukung semua operator standar dan memungkinkan Anda menulis kode seperti yang ditunjukkan di bawah ini. Ini sangat berguna.

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

1
Ini harus menjadi suara kemenangan. Asli dan dimaksudkan. Saya menemukan hampir setiap saat bahwa jika Anda menulis pembantu baru, Anda terlalu memikirkannya.
augurone

2
@ augurone ini bukan penolong asli. Jika Anda mengikuti tautan, Anda akan melihat bahwa itu adalah pembantu yang ditentukan khusus.
gfullam

@full Anda benar, saya menggunakan setang dalam merakit, yang mencakup penolong ini secara asli. Salahku.
augurone

4

Mirip dengan jawaban Jim tetapi menggunakan sedikit kreativitas kita juga bisa melakukan sesuatu seperti ini:

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

Kemudian untuk menggunakannya kita mendapatkan sesuatu seperti:

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

Saya akan menyarankan memindahkan objek keluar dari fungsi untuk kinerja yang lebih baik tetapi jika tidak Anda dapat menambahkan fungsi perbandingan yang Anda inginkan, termasuk "dan" dan "atau".


3

Satu alternatif lain adalah dengan menggunakan nama fungsi di #if. The #ifakan mendeteksi jika parameter adalah fungsi dan jika sudah maka akan menyebutnya dan menggunakan return untuk check truthyness. Di bawah ini fungsi saya mendapat konteks saat ini sebagai this.

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

Jadi Anda perlu menambahkan fungsi ke dalam konteks? Menjalankan kode dari suatu konteks adalah lubang keamanan, karena sumber kode tidak diketahui. Ini dapat dimanfaatkan untuk serangan XSS.
T Nguyen

Ya, Anda perlu menambahkan fungsi ke dalam konteks. Dalam situs web yang dirancang dengan buruk, ya, ini bisa menjadi celah keamanan. Tetapi dalam kasus itu, akan ada banyak orang lain.
Shital Shah

Ini adalah cara yang disukai .. TY.
elad.chen

3

Sayangnya tidak ada solusi yang memecahkan masalah "ATAU" operator "cond1 || cond2".

  1. Periksa apakah nilai pertama benar
  2. Gunakan "^" (atau) dan periksa apakah kond2 benar

    {{#if cond1}} MELAKUKAN TINDAKAN {{^}} {{#if cond2}} MELAKUKAN TINDAKAN {{/ if}} {{/ if}}

Itu melanggar aturan KERING. Jadi mengapa tidak menggunakan parsial untuk membuatnya tidak berantakan

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

3

Saya dapat memahami mengapa Anda ingin membuat penolong untuk situasi di mana Anda memiliki sejumlah besar perbandingan yang bervariasi untuk dilakukan dalam template Anda, tetapi untuk sejumlah kecil perbandingan (atau bahkan satu, yang merupakan apa yang membawa saya ke halaman ini di tempat pertama), mungkin akan lebih mudah untuk mendefinisikan variabel setang baru dalam panggilan fungsi rendering tampilan Anda, seperti:

Lulus ke setang saat render:

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

dan kemudian di dalam template setang Anda:

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

Saya menyebutkan ini demi kesederhanaan, dan juga karena ini merupakan jawaban yang mungkin cepat dan bermanfaat sambil tetap mematuhi sifat Setang yang tanpa logika.


3

Instal addon Pembantu Ember Truth dengan menjalankan perintah di bawah ini

bara pasang bara-kebenaran-pembantu

Anda dapat mulai menggunakan sebagian besar operator logis (eq, bukan-eq, tidak, dan, atau, gt, gte, lt, lte, xor).

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

Anda bahkan dapat memasukkan subekspresi untuk melangkah lebih jauh,

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

2

Namun solusi bengkok lainnya untuk pembantu ternary:

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

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

Atau pembantu bersatu yang sederhana:

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

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

Karena karakter ini tidak memiliki arti khusus dalam markup setang, Anda bebas menggunakannya untuk nama pembantu.


1

Saya telah menemukan paket npm yang dibuat dengan CoffeeScript yang memiliki banyak pembantu yang luar biasa berguna untuk Setang. Lihatlah dokumentasi di URL berikut:

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

Anda dapat melakukannya wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgzuntuk mengunduhnya dan melihat isi paket.

Anda akan dapat melakukan hal-hal seperti {{#is number 5}}atau{{formatDate date "%m/%d/%Y"}}


1

jika Anda hanya ingin memeriksa apakah ada satu atau elemen lain yang ada, Anda dapat menggunakan bantuan ini

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

seperti ini

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

jika Anda juga harus dapat memiliki "atau" untuk membandingkan nilai-nilai pengembalian fungsi, saya lebih suka menambahkan properti lain yang mengembalikan hasil yang diinginkan.

Lagipula templatnya harus tanpa logika!



1

Baru saja datang ke pos ini dari pencarian google tentang cara memeriksa apakah string sama dengan string lain.

Saya menggunakan HandlebarsJS di sisi server NodeJS, tetapi saya juga menggunakan file template yang sama di front-end menggunakan versi browser HandlebarsJS untuk menguraikannya. Ini berarti bahwa jika saya menginginkan pembantu kustom, saya harus mendefinisikannya di 2 tempat terpisah, atau menetapkan fungsi ke objek yang dimaksud - terlalu banyak usaha !!

Apa yang dilupakan orang adalah bahwa objek tertentu memiliki fungsi bawaan yang dapat digunakan dalam templat kumis. Dalam hal string:

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.

Kami dapat menggunakan metode ini untuk mengembalikan susunan kecocokan, atau nulljika tidak ada kecocokan yang ditemukan. Ini sempurna, karena melihat dokumentasi 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.

Begitu...

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

MEMPERBARUI:

Setelah menguji pada semua browser, ini tidak berfungsi pada Firefox . HandlebarsJS meneruskan argumen lain ke pemanggilan fungsi, yang berarti bahwa ketika String.prototype.match dipanggil, argumen kedua (yaitu flag Regexp untuk pemanggilan fungsi pencocokan sesuai dokumentasi di atas) tampaknya diteruskan. Firefox melihat ini sebagai penggunaan String.prototype.match, dan jadi rusak.

Solusinya adalah mendeklarasikan prototipe fungsional baru untuk objek String JS , dan gunakan itu sebagai gantinya:

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

Pastikan kode JS ini disertakan sebelum Anda menjalankan fungsi Handlebars.compile (), lalu di templat Anda ...

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

Diperbarui untuk Firefox, ini adalah apa yang saya gunakan saat ini
Jon

1

Di sini kita memiliki setang vanila untuk beberapa logika && dan || (dan atau):

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

Tidak yakin apakah "aman" untuk digunakan "dan" dan "atau" ... mungkin berubah menjadi sesuatu seperti "op_and" dan "op_or"?


1

Solusi yang Benar untuk DAN / ATAU

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

Kemudian panggil sebagai berikut

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

BTW: Perhatikan bahwa solusi yang diberikan di sini tidak benar, dia tidak mengurangi argumen terakhir yang merupakan nama fungsi. https://stackoverflow.com/a/31632215/1005607

AND / OR aslinya didasarkan pada daftar lengkap argumen

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

Bisakah seseorang mengubah jawaban itu? Saya hanya membuang waktu satu jam untuk mencoba memperbaiki sesuatu dalam jawaban yang direkomendasikan oleh 86 orang. Cara mengatasinya adalah memfilter argumen terakhir yang merupakan nama fungsi.Array.prototype.slice.call(arguments, 0, arguments.length - 1)


0

Mengikuti 2 panduan ini cara-untuk-membiarkan-pengguna-menentukan-membuat-terikat-jika-pernyataan dan pembantu terikat khusus saya bisa menyesuaikan pandangan bersama saya di posting ini pada stackoverflow untuk menggunakan ini alih-alih standar # jika pernyataan. Ini harus lebih aman daripada hanya melemparkan # jika ada di sana.

Pembantu terikat khusus dalam inti itu luar biasa.

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

Saya menggunakan bara cli untuk membangun aplikasi bara saya.

Pengaturan saat ini pada saat posting ini:

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

Di Ember.js Anda bisa menggunakan inline if helper in if block helper. Itu dapat menggantikan ||operator logis, misalnya:

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

0

Anda dapat melakukannya hanya dengan menggunakan operator logis seperti ini di bawah ini:

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

Sebelum menutup jika Anda dapat menulis logika bisnis Anda


0

Anda dapat menggunakan kode berikut:

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

Tolong jelaskan lebih banyak tentang pemikiran dan proses Anda, mungkin akan sangat sulit bagi orang untuk memahami solusi Anda jika mereka tidak tahu konteksnya atau masih baru dalam bahasa tersebut.
mrhn

-1

Inilah pendekatan yang saya gunakan untuk bara 1.10 dan bara-cli 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));
});

Kemudian Anda dapat menggunakannya di template Anda seperti ini:

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

Di mana argumen untuk ekspresi yang berlalu dalam sebagai p0, p1, p2dll dan p0juga dapat dirujuk sebagai this.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.