handlebars.js {{#if}}의 논리 연산자 조건부


479

핸들 바 JS에서 논리 연산자를 표준 handlebars.js 조건부 연산자에 통합하는 방법이 있습니까? 이 같은:

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

나는 내 자신의 도우미를 쓸 수 있다는 것을 알고 있지만 먼저 바퀴를 재발 명하지 않도록하고 싶습니다.

답변:


518

이것은 블록 도우미로 '속임수'를 사용하여 가능합니다. 이것은 아마도 핸들 바를 개발 한 사람들의 이념에 위배됩니다.

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

그런 다음 템플릿에서 도우미를 호출 할 수 있습니다.

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

54
이것은 Handlebars / Moustache의 논리가없는 특성에 위배되지만 그럼에도 불구하고 확실히 유용합니다. 감사합니다!
Bala Clark

6
바인딩 된 속성 (읽기, Ember 바인딩)에서는 작동하지 않습니다. 리터럴 값에는 문제가 없지만 (Ember 1.0.0-rc.8 및 Handlebars 1.0.0에서 테스트 한) 모델 속성을 해석하지 않으며 registerBoundHelperHandlebars 구문을 처리 할 수 ​​없습니다. 해결 방법은 다음과 같이 사용자 정의보기를 작성하는 것입니다. stackoverflow.com/questions/18005111/…
Warren Seine

28
@BalaClark 정말 논리가 없습니까? 나는 그것이 여전히 "if"문장을 가지고 있음을 의미합니다. 단지 의도적으로 무너져서 철학을 바꾸지 않습니다.
phreakhead

111
나는 왜 개발자들이 핸디캡을 선호하는지 이해하지 못했습니다.
StackOverflowed

36
AND / OR이 왜 핸들 바의 일부가 될 수 없는지 이해할 수 없습니다. 각이 이미 IF 않는 한, 그리고 이후는 logicless을 위해 너무 많이 ... logicless 성격에 대하여 이동하지 않습니다
Asaf

445

솔루션을 한 단계 더 발전시킵니다. 비교 연산자가 추가됩니다.

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

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

다음과 같은 템플릿에서 사용하십시오.

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

커피 스크립트 버전

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

20
'||'및 에 대해 잊지 마십시오 '&&'. 나는이 경우를 추가하고 매우 유용합니다.
Jason

20
분명하지 않은 한 가지 핸들 바에 대한 멍청한 짓은 연산자를 문자열로 전달해야합니다. 그렇지 않으면 템플릿을 토큰 화하는 동안 컴파일러에서 오류가 발생합니다. {{#ifCond true '=='false}}
Joe Holloway

2
객체 속성에 대해 평가되지 않은 값을 찾았습니다. 다음과 같은 v1 = Ember.Handlebars.get(this, v1, options) v2 = Ember.Handlebars.get(this, v2, options)
도움말

4
그러나 v1과 v2도 하나의 조건이라면 어떻게 사용할 수 있습니까? 예 : if (value == "a"|| value == "b")
Krishna

3
이것으로 다른 것을 할 수 있습니까?
jbyrd

160

핸들은 중첩 작업을 지원합니다. 논리를 조금 다르게 작성하면 유연성이 향상되고 코드가 깨끗해집니다.

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

실제로 모든 종류의 논리를 추가 할 수 있습니다.

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

다음 도우미를 등록하십시오.

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

5
Ember 1.10의 HTMLBars까지는 불가능했습니다. 또한 그 도우미는 github.com/jmurphyau/ember-truth-helpers 대신 Ember CLI 애드온으로 제공됩니다 .
stephen.hanson

1
이 방법으로 options실행이 없으면 if테스트 방법 을 유지하는 것이 좋습니다 . 감사!
Washington Botelho

25
핸들 바에 Lisp을 내장 한 것 같습니다.
jdunning

8
귀하 andor도우미는 두 가지 매개 변수로만 작동하며 이는 원하는 것이 아닙니다. 나는 둘 이상의 매개 변수를 지원하기 위해 도우미 andor도우미를 모두 재 작업했습니다 . 이 단일 라이너를 and: return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);에 사용하고이 단일 라이너를 or:에 사용하십시오 return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);.
Luke

3
각 운영자마다 여러 개의 매개 변수를 사용할 수 있는 좀 더 고급 버전 입니다.
Nate

87

가장자리에 사는 당신을 위해 이것을 한 단계 끌어 올리십시오.

요점 : https://gist.github.com/akhoury/9118682 데모 : 아래 코드 스 니펫

핸들 바 도우미 : {{#xif EXPRESSION}} {{else}} {{/xif}}

식으로 IF 문을 실행하는 도우미

  1. EXPRESSION은 올바르게 이스케이프 된 문자열입니다.
  2. 예 당신이 필요해 제대로 문자열 리터럴하거나 다른 단일 및 이중 따옴표를 탈출
  3. 모든 글로벌 기능이나 속성에 액세스 할 수 있습니다. encodeURIComponent(property)
  4. 이 예제는 당신이 당신의 핸들이 컨텍스트를 통과 가정 template( {name: 'Sam', age: '20' } ), 통지 ageA는 string내가 데모를 할 수 너무 들어, parseInt()이 게시물의 뒷부분

용법:

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

산출

<p>
  BOOM
</p>

자바 스크립트 : (다른 도우미에 따라 다름)

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

핸들 바 도우미 : {{x EXPRESSION}}

자바 스크립트 표현식을 실행하는 도우미

  1. EXPRESSION은 올바르게 이스케이프 된 문자열입니다.
  2. 예 당신이 필요해 제대로 문자열 리터럴하거나 다른 단일 및 이중 따옴표를 탈출
  3. 모든 글로벌 기능이나 속성에 액세스 할 수 있습니다. parseInt(property)
  4. 이 예제를 사용하면 핸들이 컨텍스트를 통과 가정 template( {name: 'Sam', age: '20' } ), ageA는 string데모 목적을 위해, 그것은 할 수있는 일 ..

용법:

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

산출:

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

자바 스크립트 :

구문을 확장하고 명확성을 위해 거의 각 줄에 주석을 달았 기 때문에 약간 커 보입니다.

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

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

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

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

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

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

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

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

무어

상위 범위에 액세스하려면이 범위가 약간 다릅니다. 표현식은 모든 인수의 조인입니다. 사용법 : 컨텍스트 데이터는 다음과 같습니다.

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

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

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

자바 스크립트 :

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

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

15
대단하다. 핸들 바는 무엇을 해야할지 말해주지 않습니다 :)
lemiant

1
:) 덕분에 요점 을 조금 더 업데이트하여 요점 을 약간 업데이트했습니다 (이 SO 질문과 직접 ​​관련이 없지만 핸들 바 템플릿 내에서 원하는 일을하는 정신으로) 그러나 제한 사항을 조심해야합니다. 표현 내에서 "상한 범위 수준"에 액세스 할 수있는 방법을 찾지 {{#each}} ... {{xif ' ../name === this.name' }} {{/each}}
못했습니다

1
"상한 범위 액세스"에 대한 솔루션을 찾았지만 새로운 도우미를 사용하여 업데이트 된 답변, {{z ...}}도우미
bentael을

붐! 굉장, 이제 부분 감사 덕분에 실제 상태를 할 수 있습니다 !
AncAinu

1
@rickysullivan eval(expression);은 이것을 대체하려고 시도 합니다 : eval('(function(){try{return ' + expression + ';}catch(e){}})();');-이것이 추악하다는 것을 알고 있지만 안전한 방법을 생각할 수는 없습니다-이것이 실행하기에 "빠른"것은 아닙니다. 거대한 반복.
bentael

33

도우미 함수를 작성하지 않고이 작업을 수행하는 간단한 방법이 있습니다. 템플릿 내에서 완전히 수행 할 수 있습니다.

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

편집 : 반대로 당신은 이것을하거나 할 수 있습니다 :

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

편집 / 참고 : 핸들 바의 웹 사이트 : handlebarsjs.com에서 허위 값은 다음과 같습니다.

if 도우미를 사용하여 조건부로 블록을 렌더링 할 수 있습니다. 인수가 false, undefined, null, ""또는 [] ( "거짓"값)를 반환하면 'cond'(cond1 또는 cond2와 같은)는 true로 계산되지 않습니다.


9
실제로는 두 값을 비교하지 않고 두 값이 모두 존재하는지 확인하면됩니다.
Cyril N.

3
실제로 웹 사이트에서 자바 스크립트와 동일한 방식으로 평가합니다. "if 헬퍼를 사용하여 조건부로 블록을 렌더링 할 수 있습니다. 인수가 false, undefined, null," "또는 [] ("falsy "값)를 반환하는 경우, 핸들 바는 블록을 렌더링하지 않습니다. "
Jono

1
당신이 옳습니다, 나는 먼저 테스트가 존재하는 것이 아니라 두 값을 비교하는 것이라고 생각했습니다. 내 나쁜, 미안
Cyril N.

4
제대로 작동하지 않습니다. cond1이 true이고 con2가 false이면 아무 것도 인쇄되지 않습니다.
Tessa Lau

1
안녕하세요 @TessaLau, 어디에서 왔는지 알 것 같습니다. 그러나 제어 흐름을 도출하면 첫 번째 줄에서 제어 흐름이 해당 조건으로 이동한다는 것을 알 수 있습니다.
Jono

19

여기에 게시 된 모든 답변의 한 가지 문제는 바인딩 된 속성, 즉 속성이 변경 될 때 if 조건이 다시 평가되지 않는다는 것입니다. 바인딩을 지원하는 도우미의 약간 더 고급 버전이 있습니다. Ember 소스 의 바인드 기능을 사용하는데, 이는 일반적인 Ember #if도우미 를 구현하는 데에도 사용됩니다 .

이것은 왼쪽의 단일 바인딩 속성으로 제한되며 오른쪽의 상수와 비교할 때 가장 실용적인 목적으로 충분하다고 생각합니다. 간단한 비교보다 더 진보 된 것이 필요하다면, 계산 된 속성을 선언하고 #if대신 일반 도우미를 사용하는 것이 좋습니다.

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

다음과 같이 사용할 수 있습니다.

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

Ember를 사용하는 경우 적절한 답변입니다. 언급 한 다른 솔루션은 값 대신 키를 전달합니다. BTW 덕분에 고개를 숙이고 몇 시간을 보냈습니다.
J Lee

2
HTMLBars / Ember 1.10으로 작업 한 사람이 있습니까? Ember.Handlebars.bind가 더 이상 존재하지 않는 것 같습니다.
Linda

변경 .. 다시 엠버와이 메소드는 작품을 원래는 원래 registerBoundHelper를 사용하지만이 조건을 변경하는 경우 다음은 다른 값으로 변경하지 않을과 :) 더 많이 가지고까지 투표한다
매트 Vukomanovic을

13

기본적으로 모든 이항 연산자와 함께 작동하는 개선 된 솔루션 (최소한 숫자, 문자열은 eval과 잘 작동하지 않습니다.

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

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

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

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

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

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

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

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

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

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

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

템플릿에서 이것을 어떻게 사용 하시겠습니까? 특히 options.fn 부분?
qodeninja

{{ifCond val1 '||' val2}} true {{else}} false {{/ if}} 올바른 경우 options.fn (true, ifCond 절)을 반환하고, 그렇지 않으면 잘못된 경우 options.inverse (false, else 절)를 반환합니다.
Nick Kitto

1
스크립트 삽입에 대한주의 사항 때문에이 도우미를 사용하지 않는 것이 좋습니다. 큰 코드베이스에서 이것은 쉽게 불쾌한 보안 문제를 일으킬 수 있습니다.
Jordan Sitkin

8

여러 조건을 확인하려는 경우 해결책이 있습니다.

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

용법:

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

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

7

내가 사용하는 블록 도우미에 대한 링크는 다음과 같습니다 : 비교 블록 도우미 . 모든 표준 연산자를 지원하며 아래와 같이 코드를 작성할 수 있습니다. 정말 편리합니다.

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

1
이기는 투표입니다. 기본적이고 의도적입니다. 나는 당신이 새로운 도우미를 쓰고 있다면 그것을 너무 많이 생각할 때마다 거의 모든 것을 발견합니다.
augurone

2
@augurone 이것은 기본 도우미가 아닙니다. 링크를 따라 가면 사용자 정의 된 헬퍼임을 알 수 있습니다.
gfullam

@ gfullam 당신 말이 맞아요, 나는이 도우미를 기본적으로 포함하는 조립 핸들을 사용하고있었습니다. 내 잘못이야.
augurone

4

Jim의 대답과 비슷하지만 약간의 창의력을 사용하여 다음과 같이 할 수도 있습니다.

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

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

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

그런 다음 사용하려면 다음과 같은 것을 얻습니다.

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

더 나은 성능을 위해 객체를 함수 밖으로 옮기는 것이 좋습니다. 그렇지 않으면 "and"및 "or"를 포함하여 원하는 비교 함수를 추가 할 수 있습니다.


3

다른 대안은에서 함수 이름을 사용하는 것입니다 #if. 는 #if매개 변수가 함수 인 경우 감지하고 그 다음 경우 그것을 전화 truthyness 검사에 대한 반환을 사용합니다. myFunction 아래에서 현재 컨텍스트를로 가져옵니다 this.

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

컨텍스트에 함수를 추가해야합니까? 코드 소스를 알 수 없기 때문에 컨텍스트에서 코드를 실행하는 것은 보안상의 허점입니다. 이것은 XSS 공격에 악용 될 수 있습니다.
T Nguyen

예, 컨텍스트에 기능을 추가해야합니다. 잘못 설계된 웹 사이트에서는 그렇습니다. 이것은 보안상의 허점이 될 수 있습니다. 그러나이 경우 다른 많은 것들이있을 것입니다.
Shital Shah

이것이 선호되는 방법입니다. TY.
elad.chen

3

불행히도 이러한 솔루션 중 어느 것도 "OR"연산자 "cond1 || cond2"의 문제를 해결하지 못합니다.

  1. 첫 번째 값이 참인지 확인
  2. "^"(또는)를 사용하고 그렇지 않으면 cond2가 true인지 확인하십시오.

    {{#if cond1}} 작업 수행 {{^}} {{#if cond2}} 작업 수행 {{/ if}} {{/ if}}

DRY 규칙을 위반합니다. 왜 부분적으로 덜 지저분하지 않게합니까?

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

3

템플릿 내에서 수행 할 수있는 다양한 비교가 많지만 비교적 적은 수의 비교 (또는이 페이지로 이동 한 비교)에 대해 도우미를 만들고 싶은 이유를 이해할 수 있습니다. 첫 번째 장소), 뷰 렌더링 함수 호출에서 다음과 같이 새 핸들 바 변수를 정의하는 것이 더 쉬울 것입니다.

렌더시 핸들 바로 전달 :

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

핸들 바 템플릿 내에서 :

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

나는 이것을 단순화하기 위해 언급했으며, 또한 핸들 바의 논리가없는 특성을 계속 준수하면서 빠르고 도움이 될 수있는 대답이기 때문에 언급했습니다.


3

아래 명령을 실행하여 Ember Truth Helpers addon을 설치 하십시오

ember 설치 ember-truth-helpers

대부분의 논리 연산자 (eq, not-eq, not, and, or, gt, gte, lt, lte, xor)를 사용할 수 있습니다.

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

더 나아 가기 위해 하위 표현식을 포함시킬 수도 있습니다.

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

2

삼항 헬퍼를위한 또 다른 비뚤어진 해결책 :

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

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

또는 간단한 통합 도우미 :

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

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

이러한 문자는 핸들 바 마크 업에서 특별한 의미가 없으므로 도우미 이름으로 자유롭게 사용할 수 있습니다.


1

HandleScripts에 유용한 유용한 도우미가 많은 CoffeeScript로 만든 npm 패키지를 찾았습니다. 다음 URL에서 설명서를 살펴보십시오.

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

wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgz를 다운로드하여 패키지의 내용을 볼 수 있습니다 .

당신은 {{#is number 5}}또는 같은 일을 할 수있을 것입니다{{formatDate date "%m/%d/%Y"}}


1

하나 또는 다른 요소가 있는지 확인하려는 경우이 사용자 정의 도우미를 사용할 수 있습니다

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

이처럼

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

함수 반환 값 을 비교하기 위해 "또는"을 가질 수 있어야하는 경우 원하는 결과를 반환하는 다른 속성을 추가하려고합니다.

템플릿은 결국 논리가 없어야합니다!



1

문자열이 다른 문자열과 같은지 확인하는 방법에 대한 Google 검색 에서이 게시물을 보냈습니다.

NodeJS 서버 측에서 HandlebarsJS를 사용하지만 브라우저 버전의 HandlebarsJS를 사용하여 프런트 엔드에서 동일한 템플릿 파일을 사용하여 구문 분석합니다. 이것은 내가 커스텀 헬퍼를 원한다면 그것을 2 개의 별도의 장소에서 정의하거나 문제의 객체에 기능을 할당해야한다는 것을 의미했습니다. 너무 많은 노력 !!

사람들이 잊어 버린 것은 특정 객체에 콧수염 템플릿에서 사용할 수있는 기능을 상속한다는 것입니다. 문자열의 경우 :

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

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

이 메소드를 사용하여 일치하는 배열을 찾거나 null일치하는 항목을 찾지 못할 수 있습니다. HandlebarsJS 설명서 http://handlebarsjs.com/builtin_helpers.html을 보고 있기 때문에 완벽합니다 .

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

그래서...

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

최신 정보:

모든 브라우저에서 테스트 한 후에 는 Firefox에서 작동하지 않습니다 . HandlebarsJS는 다른 인수를 함수 호출에 전달합니다. 즉, String.prototype.match가 호출되면 두 번째 인수 (즉, 위의 문서에 따라 일치 함수 호출에 대한 Regexp 플래그)가 전달되는 것으로 나타납니다. Firefox는 이것을 사용되지 않는 String.prototype.match 사용으로 간주하므로 중단됩니다.

해결 방법은 String JS 객체의 새 기능 프로토 타입을 선언하고 대신 사용하는 것입니다.

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

이 JS 코드가 포함되어 있는지 확인 하기 전에 당신이 당신의 템플릿에 다음, 당신의 Handlebars.compile () 함수를 실행 ...

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

Firefox 용으로 업데이트되었습니다. 현재 사용중인 것입니다
Jon

1

여기에 여러 논리 && 및 ||에 대한 바닐라 핸들 바가 있습니다. (또는) :

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

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

    return options.fn(this);
});


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

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

    return options.inverse(this);
}

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

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

"and"및 "or"를 사용하는 것이 "안전한"지 확실하지 않은 경우 ... "op_and"및 "op_or"와 같은 것으로 변경 될 수 있습니까?


1

AND / OR에 대한 올바른 솔루션

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

다음과 같이 전화하십시오

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

BTW : 여기에 주어진 해결책은 정확하지 않으며, 함수 이름 인 마지막 인수를 빼지 않습니다. https://stackoverflow.com/a/31632215/1005607

그의 원래 AND / OR는 전체 인수 목록을 기반으로했습니다.

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

누군가 그 대답을 바꿀 수 있습니까? 86 명이 권장하는 답변으로 무언가를 고치려고 한 시간을 낭비했습니다. 수정은 함수 이름 인 마지막 인수 를 필터링하는 것 입니다.Array.prototype.slice.call(arguments, 0, arguments.length - 1)


0

이 2 개의 가이드에게 다음 A-방법에 시켰 사용자 것은 - 정의 - 사용자 정의 만든 바인딩 - 명령문 경우사용자 정의 바인딩 헬퍼 나는이 게시물에 내 공유 뷰를 조정할 수 있었다 유래 표준 # 대신이 사용하기 if 문. #if를 던지는 것보다 더 안전해야합니다.

그 요점의 맞춤형 바운드 도우미는 뛰어납니다.

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

ember cli 프로젝트를 사용하여 ember 애플리케이션을 빌드하고 있습니다.

이 게시물 당시의 현재 설정 :

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

0

Ember.js에서는 if 블록 도우미에 인라인 if 도우미 를 사용할 수 있습니다 . ||논리 연산자 를 대체 할 수 있습니다 ( 예 :

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

0

아래와 같이 논리 연산자를 사용하여 간단하게 수행 할 수 있습니다.

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

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

비즈니스 로직을 작성할 수있는 경우 닫기 전에


0

다음 코드를 사용할 수 있습니다 :

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

당신의 생각과 과정에 대해 더 많은 것을 설명하십시오. 사람들이 문맥을 모르거나 언어에 익숙하지 않은 경우 솔루션을 이해하기가 매우 어려울 수 있습니다.
mrhn

-1

ember 1.10 및 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));
});

그런 다음 템플릿에서 다음과 같이 사용할 수 있습니다.

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

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

식에 인수로 전달되는 경우 p0, p1, p2등 및 p0로도 참조 할 수 있습니다 this.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.