Toán tử logic trong một tệp điều khiển có điều kiện {{#if}}


479

Có cách nào trong trình điều khiển JS để kết hợp các toán tử logic vào toán tử điều kiện tiêu chuẩn của handbars.js không? Một cái gì đó như thế này:

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

Tôi biết tôi có thể viết người trợ giúp của riêng mình, nhưng trước tiên tôi muốn chắc chắn rằng tôi không phát minh lại bánh xe.

Câu trả lời:


519

Điều này có thể bằng cách 'gian lận' với một người trợ giúp khối. Điều này có lẽ đi ngược lại với Tư tưởng của những người đã phát triển Tay lái.

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

Sau đó, bạn có thể gọi người trợ giúp trong mẫu như thế này

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

54
Điều này không đi ngược lại với bản chất phi logic của Tay cầm / Râu, nhưng chắc chắn là hữu ích dù sao, cảm ơn!
Bala Clark

6
Lưu ý rằng điều này chỉ đơn giản là không hoạt động với các thuộc tính ràng buộc (đọc, ràng buộc Ember). Nó ổn với các giá trị theo nghĩa đen, nhưng không giải quyết các thuộc tính mô hình (được thử nghiệm với Ember 1.0.0-rc.8 và Tay cầm 1.0.0) và registerBoundHelperkhông thể xử lý cú pháp Tay cầm. Cách giải quyết là tạo chế độ xem tùy chỉnh: stackoverflow.com/questions/18005111/ mẹo
Warren Seine

28
@BalaClark có thực sự logic không? Ý tôi là nó vẫn có câu "nếu" - chỉ vì chúng bị làm tê liệt có chủ ý không làm thay đổi triết lý.
phreakhead

111
Tôi không bao giờ hiểu tại sao các nhà phát triển thích tàn tật.
StackOverflow

36
Tôi không hiểu tại sao VÀ / HOẶC không thể là một phần của Tay lái. Nó không đi ngược lại với bản chất phi logic vì đã có IF, UNLESS và MACHI ... rất nhiều cho việc không logic
Asaf

445

Đưa giải pháp tiến thêm một bước. Điều này thêm toán tử so sánh.

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

Sử dụng nó trong một mẫu như thế này:

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

Phiên bản cà phê Script

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
đừng quên '||''&&'. Tôi đã thêm những trường hợp này và chúng rất hữu ích.
Jason

20
Là một người không biết xử lý một điều không rõ ràng là bạn phải truyền toán tử dưới dạng một chuỗi nếu không trình biên dịch sẽ báo lỗi trong khi mã hóa mẫu của bạn. {{#ifCond đúng '==' sai}}
Joe Holloway

2
Tôi tìm thấy các giá trị không được đánh giá cho các thuộc tính đối tượng. Thêm các trợ giúp sau v1 = Ember.Handlebars.get(this, v1, options) v2 = Ember.Handlebars.get(this, v2, options)
ZX12R 3/03/2015

4
Nhưng nếu v1 và v2 cũng có một điều kiện thì làm sao tôi có thể sử dụng? ví dụ: if (value == "a" || value == "b")
Krishna

3
Bạn có thể làm khác nếu với điều này?
jbyrd

160

Tay lái hỗ trợ các hoạt động lồng nhau. Điều này cung cấp rất nhiều tính linh hoạt (và mã sạch hơn) nếu chúng ta viết logic của chúng tôi một chút khác nhau.

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

Trong thực tế, chúng ta có thể thêm tất cả các loại logic:

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

Chỉ cần đăng ký những người trợ giúp này:

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
Lưu ý rằng điều này là không thể cho đến khi HTMLBars trong Ember 1.10. Ngoài ra, những người trợ giúp này đến như một addon Ember CLI nếu bạn muốn: github.com/jmurphyau/ember-truth-helpers .
stephen.hanson

1
Bằng cách này, không có optionsthực thi sẽ tốt hơn để giữ bằng ifphương pháp và dễ kiểm tra hơn. Cảm ơn!
Washington Botelho

25
Chúng tôi dường như đã xây dựng Lisp thành Tay cầm.
vui vẻ

8
Bạn andorngười trợ giúp chỉ làm việc với 2 tham số, đó không phải là điều bạn muốn. Tôi quản lý để làm lại cả hai andorngười trợ giúp để hỗ trợ nhiều hơn hai tham số. Sử dụng một lớp lót này cho and: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);và sử dụng một lớp lót này cho or: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);.
Lu-ca

3
Một phiên bản nâng cao hơn một chút có thể lấy nhiều tham số trên mỗi toán tử.
Nate

87

đưa cái này lên một bậc, cho những người sống ở rìa.

ý chính : https://gist.github.com/akhoury/9118682 Demo : Đoạn mã dưới đây

Tay lái trợ giúp: {{#xif EXPRESSION}} {{else}} {{/xif}}

một người trợ giúp để thực hiện một câu lệnh IF với bất kỳ biểu thức nào

  1. EXPRESSION là một chuỗi thoát đúng
  2. Có, bạn CẦN thoát khỏi chuỗi ký tự hoặc chỉ thay thế dấu ngoặc đơn và dấu ngoặc kép
  3. bạn có thể truy cập bất kỳ chức năng hoặc tài sản toàn cầu tức là encodeURIComponent(property)
  4. ví dụ này giả sử bạn đã chuyển ngữ cảnh này tới tay lái của bạn template( {name: 'Sam', age: '20' } ), thông báo agestring, chỉ để tôi có thể demo parseInt()sau trong bài đăng này

Sử dụng:

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

Đầu ra

<p>
  BOOM
</p>

JavaScript: (nó phụ thuộc vào người trợ giúp khác - tiếp tục đọc)

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

Tay lái trợ giúp: {{x EXPRESSION}}

Một người trợ giúp để thực hiện các biểu thức javascript

  1. EXPRESSION là một chuỗi thoát đúng
  2. Có, bạn CẦN thoát khỏi chuỗi ký tự hoặc chỉ thay thế dấu ngoặc đơn và dấu ngoặc kép
  3. bạn có thể truy cập bất kỳ chức năng hoặc tài sản toàn cầu tức là parseInt(property)
  4. ví dụ này giả sử bạn đã chuyển ngữ cảnh này tới tay lái của bạn template( {name: 'Sam', age: '20' } ), agestringcho mục đích demo, nó có thể là bất cứ điều gì ..

Sử dụng:

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

Đầu ra:

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

JavaScript:

Điều này có vẻ hơi lớn vì tôi đã mở rộng cú pháp và nhận xét trên hầu hết các dòng cho mục đích rõ ràng

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

Nếu bạn muốn truy cập phạm vi cấp trên, thì phạm vi này hơi khác một chút, biểu thức là THAM GIA của tất cả các đối số, cách sử dụng: giả sử dữ liệu ngữ cảnh trông như thế này:

// 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
Điều đó thật tuyệt. Tay lái không thể cho bạn biết phải làm gì :)
lemiant

1
:) cảm ơn, tôi đã cập nhật ý chính một chút để thêm một vài điều tốt đẹp (không liên quan trực tiếp đến câu hỏi SO này - nhưng trên tinh thần làm những gì bạn muốn trong một mẫu tay lái) Tuy nhiên, bạn nên đề phòng những hạn chế, tôi tránh Tôi không tìm thấy cách nào để truy cập "các mức phạm vi trên" từ trong biểu thức, giả sử bạn ở trong từng phạm vi, {{#each}} ... {{xif ' ../name === this.name' }} {{/each}}... nhưng tôi vẫn đang điều tra ..
bentael

1
tìm thấy một giải pháp cho "truy cập phạm vi trên" nhưng sử dụng một người trợ giúp mới, xem câu trả lời được cập nhật, {{z ...}}người trợ giúp
bentael

BÙM! Tuyệt vời, bây giờ tôi có thể làm điều kiện thực sự trong một phần cảm ơn của tôi !
AncAinu

1
@rickysullivan thử thay thế eval(expression);bằng cái này: eval('(function(){try{return ' + expression + ';}catch(e){}})();');- Tôi biết điều này đang trở nên xấu xí, nhưng không thể nghĩ ra một cách an toàn để làm điều này - xin lưu ý rằng việc này không thực sự "nhanh", tôi sẽ không làm điều này trong số lần lặp rất lớn.
bentael

33

Có một cách đơn giản để làm điều này mà không cần viết hàm trợ giúp ... Nó hoàn toàn có thể được thực hiện trong khuôn mẫu.

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

Chỉnh sửa: Ngược lại, bạn có thể làm hoặc bằng cách này:

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

Chỉnh sửa / Lưu ý: Từ trang web của tay cầm: handlebarsjs.com ở đây là các giá trị giả:

Bạn có thể sử dụng if helper để tạo điều kiện một khối. Nếu đối số của nó trả về false, không xác định, null, "" hoặc [] (giá trị "giả"), thì mọi 'cond' (như cond1 hoặc cond2) sẽ không được tính là đúng.


9
Không thực sự, bạn không so sánh hai giá trị, bạn chỉ cần đảm bảo cả hai giá trị tồn tại, nó khác nhau.
Cyril N.

3
Trên thực tế, nó đánh giá nó giống như cách javascript thực hiện, từ trang web: "Bạn có thể sử dụng trình trợ giúp if để hiển thị một cách có điều kiện một khối. Nếu đối số của nó trả về false, không xác định, null," "hoặc [] (giá trị" giả "), Tay lái sẽ không kết xuất khối. "
Jono

1
Bạn nói đúng, trước tiên tôi nghĩ thử nghiệm là so sánh hai giá trị, không phải thử nghiệm cả hai tồn tại. Xấu của tôi, xin lỗi
Cyril N.

4
Điều này không hoạt động chính xác. Nếu cond1 là true và con2 là false, sẽ không có gì được in.
Tessa Lau

1
Xin chào @TessaLau, tôi nghĩ tôi thấy bạn đến từ đâu. Tuy nhiên, nếu bạn rút ra một luồng điều khiển, bạn sẽ thấy rằng trong dòng đầu tiên sẽ di chuyển luồng điều khiển đến điều kiện đó.
Jono

19

Một vấn đề với tất cả các câu trả lời được đăng ở đây là chúng không hoạt động với các thuộc tính bị ràng buộc, tức là điều kiện if không được đánh giá lại khi các thuộc tính liên quan thay đổi. Đây là phiên bản nâng cao hơn một chút của trình trợ giúp hỗ trợ các ràng buộc. Nó sử dụng chức năng liên kết từ nguồn Ember, cũng được sử dụng để thực hiện trình #iftrợ giúp Ember bình thường .

Cái này được giới hạn trong một thuộc tính ràng buộc duy nhất ở phía bên trái, so với hằng số ở phía bên phải, mà tôi nghĩ là đủ tốt cho hầu hết các mục đích thực tế. Nếu bạn cần một cái gì đó cao cấp hơn so với một so sánh đơn giản, thì có lẽ sẽ tốt hơn nếu bắt đầu khai báo một số thuộc tính được tính toán và sử dụng trình #iftrợ giúp thông thường thay thế.

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

Bạn có thể sử dụng nó như thế này:

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

Đây là câu trả lời thích hợp nếu bạn đang sử dụng Ember. Các giải pháp khác như bạn đã đề cập sẽ chỉ chuyển khóa thay vì giá trị. Cảm ơn BTW vì điều này, đã dành vài giờ để vùi đầu tôi.
J Lee

2
Có ai đã làm việc này với HTMLBars / Ember 1.10 chưa? Ember.Handlebars.bind dường như không còn tồn tại.
Linda

Ban đầu tôi đã sử dụng registerBoundHelper ban đầu nhưng sau đó khi nó thay đổi điều kiện thì nó sẽ không đổi sang giá trị khác và quay lại .. Phương pháp này hoạt động với ember để thay đổi :) Nó sẽ có nhiều phiếu bầu hơn
Matt Vukomanovic

13

Giải pháp cải tiến về cơ bản hoạt động với bất kỳ toán tử nhị phân nào (ít nhất là số, chuỗi không hoạt động tốt với eval, HÃY CHĂM SÓC SỨC KHỎE KHAI THÁC NẾU NẾU SỬ DỤNG HOẠT ĐỘNG KHÔNG ĐƯỢC ĐỊNH NGHFA VỚI NGƯỜI DÙNG NGƯỜI DÙNG):

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

Làm thế nào bạn sẽ sử dụng điều này trong một mẫu? đặc biệt là phần tùy chọn.fn?
qodeninja

{{ifCond val1 '||' val2}} true {{other}} false {{/ if}} nó trả về tùy chọn.fn (true, mệnh đề ifCond) nếu đúng, nếu không, nó trả về tùy chọn.inverse (false, mệnh đề khác) nếu không chính xác.
Nick Kitto

1
Do sự cảnh báo được đề cập về việc tiêm script, tôi thực sự khuyên bạn không nên sử dụng trình trợ giúp này. Trong một cơ sở mã lớn, điều này có thể dễ dàng chịu trách nhiệm cho một vấn đề bảo mật khó chịu ở tuyến dưới
Jordan Sitkin

8

Đây là một giải pháp nếu bạn muốn kiểm tra nhiều điều kiện:

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

Sử dụng:

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

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

7

Đây là một liên kết đến trình trợ giúp khối tôi sử dụng: trình trợ giúp khối so sánh . Nó hỗ trợ tất cả các toán tử tiêu chuẩn và cho phép bạn viết mã như hiển thị bên dưới. Nó thực sự khá tiện dụng.

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

1
Đây phải là phiếu bầu chiến thắng. Bản địa và dự định. Tôi thấy hầu như mọi lúc nếu bạn viết một người trợ giúp mới, bạn sẽ lật đổ nó.
augurone 17/2/2015

2
@augurone đây không phải là một người trợ giúp bản địa. Nếu bạn theo liên kết, bạn sẽ thấy đó là một trình trợ giúp được xác định tùy chỉnh.
gfullam

@gfullam bạn nói đúng, tôi đã sử dụng tay lái để lắp ráp, trong đó bao gồm cả trình trợ giúp này. Lỗi của tôi.
augurone

4

Tương tự như câu trả lời của Jim nhưng sử dụng một chút sáng tạo, chúng ta cũng có thể làm một cái gì đó như thế này:

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

Sau đó, để sử dụng nó, chúng tôi nhận được một cái gì đó như:

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

Tôi sẽ đề nghị di chuyển đối tượng ra khỏi chức năng để có hiệu suất tốt hơn nhưng nếu không, bạn có thể thêm bất kỳ chức năng so sánh nào bạn muốn, bao gồm "và" và "hoặc".


3

Một cách khác là sử dụng tên hàm trong #if. Các #ifsẽ phát hiện nếu tham số là chức năng và nếu nó là sau đó nó sẽ gọi nó và sử dụng lợi nhuận của mình để kiểm tra truthyness. Dưới myFactor có bối cảnh hiện tại là this.

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

Vì vậy, bạn sẽ cần phải thêm một chức năng vào bối cảnh? Thực thi mã từ một bối cảnh là một lỗ hổng bảo mật, vì nguồn của mã có thể không xác định. Điều này có thể được khai thác cho một cuộc tấn công XSS.
T Nguyễn

Có, bạn cần thêm chức năng vào ngữ cảnh. Trong một trang web được thiết kế tồi, vâng, đây có thể là lỗ hổng bảo mật. Nhưng trong trường hợp đó, sẽ có nhiều người khác.
Shital Shah

Đây là cách ưa thích .. TY.
elad.chen

3

Thật không may, không có giải pháp nào trong số này giải quyết được vấn đề của toán tử "HOẶC" cond1 || cond2 ".

  1. Kiểm tra xem giá trị đầu tiên có đúng không
  2. Sử dụng "^" (hoặc) và kiểm tra xem cond2 có đúng không

    {{#if cond1}} HÃY HÀNH ĐỘNG {{^}} {{#if cond2}} HÃY HÀNH ĐỘNG {{/ if}} {{/ if}}

Nó phá vỡ quy tắc DRY. Vậy tại sao không sử dụng một phần để làm cho nó bớt lộn xộn

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

3

Tôi có thể hiểu lý do tại sao bạn muốn tạo một người trợ giúp cho các tình huống trong đó bạn có một số lượng lớn các so sánh khác nhau để thực hiện trong mẫu của mình, nhưng đối với một số lượng so sánh tương đối nhỏ (hoặc thậm chí là một, đó là điều đã đưa tôi đến trang này trong vị trí đầu tiên), có thể sẽ dễ dàng hơn để xác định biến điều khiển mới trong lệnh gọi hàm hiển thị chế độ xem của bạn, như:

Chuyển đến tay lái khi kết xuất:

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

và sau đó trong mẫu tay lái của bạn:

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

Tôi đề cập đến điều này vì đơn giản, và cũng bởi vì đó là một câu trả lời có thể nhanh chóng và hữu ích trong khi vẫn tuân thủ bản chất phi logic của Tay cầm.


3

Cài đặt addon Ember Truth Helpers bằng cách chạy lệnh bên dưới

ember cài đặt ember-Truth-helpers

bạn có thể bắt đầu sử dụng hầu hết các toán tử logic (eq, not-eq, not, và, hoặc, gt, gte, lt, lte, xor).

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

Bạn thậm chí có thể bao gồm biểu hiện phụ để đi xa hơn,

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

2

Một giải pháp quanh co khác cho một người trợ giúp ternary:

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

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

Hoặc một người trợ giúp hợp nhất đơn giản:

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

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

Vì các ký tự này không có ý nghĩa đặc biệt trong đánh dấu tay lái, nên bạn có thể sử dụng chúng cho tên người trợ giúp.


1

Tôi đã tìm thấy một gói npm được tạo bằng CoffeeScript có rất nhiều trình trợ giúp hữu ích đáng kinh ngạc cho Tay cầm. Hãy xem tài liệu trong URL sau:

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

Bạn có thể làm một wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgzđể tải về chúng và xem nội dung của gói.

Bạn sẽ được chấp nhận làm những việc như {{#is number 5}}hoặc{{formatDate date "%m/%d/%Y"}}


1

nếu bạn chỉ muốn kiểm tra xem một hoặc một yếu tố khác có mặt hay không, bạn có thể sử dụng trình trợ giúp tùy chỉnh này

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

như thế này

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

nếu bạn cũng cần có khả năng "hoặc" để so sánh các giá trị trả về của hàm, tôi muốn thêm một thuộc tính khác trả về kết quả mong muốn.

Các mẫu nên không logic sau khi tất cả!



1

Chỉ cần đến bài đăng này từ một tìm kiếm google về cách kiểm tra xem một chuỗi có bằng một chuỗi khác không.

Tôi sử dụng HandbarsJS trong phía máy chủ NodeJS, nhưng tôi cũng sử dụng các tệp mẫu tương tự ở mặt trước bằng cách sử dụng phiên bản trình duyệt của HandbarsJS để phân tích cú pháp. Điều này có nghĩa là nếu tôi muốn một người trợ giúp tùy chỉnh, tôi phải xác định nó ở 2 vị trí riêng biệt hoặc gán một hàm cho đối tượng được đề cập - quá nhiều nỗ lực !!

Điều mọi người quên là các đối tượng nhất định có các hàm kế thừa có thể được sử dụng trong mẫu ria mép. Trong trường hợp của một chuỗi:

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.

Chúng ta có thể sử dụng phương pháp này để trả về một mảng các trận đấu hoặc nullnếu không tìm thấy kết quả khớp nào. Điều này là hoàn hảo, bởi vì hãy xem tài liệu của HandbarsJS 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.

Vì thế...

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

CẬP NHẬT:

Sau khi thử nghiệm trên tất cả các trình duyệt, điều này không hoạt động trên Firefox . HandbarsJS chuyển các đối số khác cho một lệnh gọi hàm, nghĩa là khi String.prototype.match được gọi, đối số thứ hai (tức là các cờ Regapi cho lệnh gọi hàm khớp theo tài liệu trên) dường như được truyền. Firefox thấy điều này là việc sử dụng String.prototype.match không được chấp nhận và do đó bị phá vỡ.

Cách giải quyết là khai báo một nguyên mẫu chức năng mới cho đối tượng String JS và sử dụng thay thế:

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

Đảm bảo mã JS này được bao gồm trước khi bạn chạy hàm Handlebars.compile (), sau đó trong mẫu của bạn ...

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

Được cập nhật cho Firefox, đây là những gì tôi hiện đang sử dụng
Jon

1

Ở đây chúng tôi có các tay lái vanilla cho nhiều logic && và || (và hoặc):

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

Không chắc chắn nếu nó "an toàn" để sử dụng "và" và "hoặc" ... có thể thay đổi thành một cái gì đó như "op_and" và "op_or"?


1

Giải pháp đúng cho VÀ / HOẶC

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

Sau đó gọi như sau

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

BTW: Lưu ý rằng giải pháp đưa ra ở đây là không chính xác, anh ta không trừ đi đối số cuối cùng là tên hàm. https://stackoverflow.com/a/31632215/1005607

AND / OR ban đầu của anh ấy được dựa trên danh sách đầy đủ các đối số

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

Ai đó có thể thay đổi câu trả lời? Tôi chỉ lãng phí một giờ để cố gắng sửa một cái gì đó trong câu trả lời được đề nghị bởi 86 người. Cách khắc phục là lọc ra đối số cuối cùng là tên hàm.Array.prototype.slice.call(arguments, 0, arguments.length - 1)


0

Thực hiện theo 2 hướng dẫn này một cách để cho phép người dùng xác định tùy chỉnh được thực hiện ràng buộc nếu câu lệnh và trình trợ giúp ràng buộc tùy chỉnh Tôi có thể điều chỉnh các chế độ xem được chia sẻ của mình trong bài đăng này trên stackoverflow để sử dụng thay vì # tiêu chuẩn nếu tuyên bố. Điều này sẽ an toàn hơn là chỉ ném một #if vào đó.

Các trợ giúp ràng buộc tùy chỉnh trong ý chính đó là xuất sắc.

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

Tôi đang sử dụng than hồng dự án để xây dựng ứng dụng than hồng của mình.

Thiết lập hiện tại tại thời điểm của bài viết này:

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

Trong Ember.js, bạn có thể sử dụng nội tuyến if helper in if block helper. Nó có thể thay thế ||toán tử logic, ví dụ:

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

0

Bạn có thể làm điều đó một cách đơn giản bằng cách sử dụng toán tử logic như thế này được hiển thị bên dưới:

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

Trước khi đóng nếu bạn có thể viết logic kinh doanh của bạn


0

Bạn có thể sử dụng mã sau đây:

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

Vui lòng giải thích thêm về suy nghĩ và quy trình của bạn, mọi người có thể rất khó hiểu giải pháp của bạn nếu họ không biết ngữ cảnh hoặc chưa quen với ngôn ngữ này.
mrhn

-1

Đây là một cách tiếp cận tôi đang sử dụng cho ember 1.10 và ember-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));
});

Sau đó, bạn có thể sử dụng nó trong các mẫu của bạn như thế này:

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

Trong trường hợp các đối số để biểu thức được thông qua tại như p0, p1, p2vv và p0cũng có thể được tham chiếu như this.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.