핸들 바를 통한 변수 전달


131

현재 express.js 응용 프로그램에서 handlebars.js를 다루고 있습니다. 모듈 식으로 유지하기 위해 모든 템플릿을 부분적으로 분할했습니다.

내 문제 : 부분 호출을 통해 변수를 전달하는 방법을 찾을 수 없습니다. 다음과 같은 부분이 있다고 가정 해 봅시다.

<div id=myPartial>
    <h1>Headline<h1>
    <p>Lorem ipsum</p>
</div>

이 부분을 'myPartial'이라는 이름으로 등록했다고 가정 해 봅시다. 다른 템플릿에서 다음과 같이 말할 수 있습니다.

<section>
    {{> myPartial}}
</section>

이것은 잘 작동하고 부분은 예상대로 렌더링되며 나는 행복한 개발자입니다. 그러나 지금 필요한 것은이 호출을 통해 다른 변수를 전달하여 헤드 라인이 제공되는지 여부와 같은 부분을 확인하는 방법입니다. 다음과 같은 것 :

<div id=myPartial>
    {{#if headline}}
    <h1>{{headline}}</h1>
    {{/if}}
    <p>Lorem Ipsum</p>
</div>

그리고 호출은 다음과 같아야합니다.

<section>
    {{> myPartial|'headline':'Headline'}}
</section>

정도.

템플릿을 렌더링하기 전에 필요한 모든 데이터를 정의 할 수 있다는 것을 알고 있습니다. 그러나 방금 설명한대로 수행 할 수있는 방법이 필요합니다. 가능한 방법이 있습니까?

답변:


214

핸들 바 부분은 두 번째 매개 변수를 취하며 부분에 대한 컨텍스트가됩니다.

{{> person this}}

버전 v2.0.0 alpha 이상에서는 명명 된 매개 변수의 해시를 전달할 수도 있습니다.

{{> person headline='Headline'}}

당신은 이러한 시나리오에 대한 테스트를 볼 수 있습니다 https://github.com/wycats/handlebars.js/blob/ce74c36118ffed1779889d97e6a2a1028ae61510/spec/qunit_spec.js#L456-L462 https://github.com/wycats/handlebars.js/ blob / e290ec24f131f89ddf2c6aeb707a4884d41c3c6d / spec / partials.js # L26-L32


5
이것이 귀하의 시나리오에 어떻게 적용되는지 확실하지 않습니까? 솔루션을 적어 주시겠습니까? 귀하의 경우에 적용하십시오. 감사!
serverman

12
@Yehuda Katz는 대신에 this자신의 상황에 따라 전달할 수 있습니다. 예를 들어 {new_variable: some_data}? 와 같이 전달할 추가 데이터를 정의하십시오 .
Tri Nguyen

22
"this"를 전달할 수있는 능력은 좋지만 항상 충분하지는 않습니다. 종종 같은 페이지에서 특정 HTML 부분을 재사용하고 싶지만 부분에 ID가 있으면 파산됩니다. 동일한 ID가 두 번 이상 표시되어 유효하지 않게됩니다. 호출 할 때 부분에 인수를 전달하여 내용을 추가로 사용자 정의 할 수 있다면 매우 유용합니다.
Xavier_Ex

2
어떤 버전의 핸들 바가이를 지원합니까? 1.3.0을 사용하고 있으며 다음을 통해 json을 전달하려고 할 때 컴파일 오류가 발생합니다.{{> partialName {new_variable: some_data} }}
bafromca

1
@bafromca는 임의의 데이터를 전달할 수 없지만 하나의 객체 만 전달하는 정확한 문제입니다. 따라서 이것을 전달하거나 컨트롤러 또는 뷰에서 json-data를 반환하는 새 속성을 만듭니다. 두 번째 형식으로 임의의 데이터를 부분적으로 전달할 수 있어야합니다 key=value. github 에서이 문제를 다루는 데 문제가 있습니까?
ohcibi

18

만약을 대비해서, 부분적인 논증을 얻기 위해 내가 한 일이 있습니다. 부분 이름과 부분에 전달되는 매개 변수의 해시를 취하는 작은 도우미를 만들었습니다.

Handlebars.registerHelper('render', function(partialId, options) {
  var selector = 'script[type="text/x-handlebars-template"]#' + partialId,
      source = $(selector).html(),
      html = Handlebars.compile(source)(options.hash);

  return new Handlebars.SafeString(html);
});

여기서 중요한 것은 Handlebars 도우미가 Ruby와 같은 인수 해시를 허용 한다는 것 입니다. 헬퍼 코드에서 그것들은 함수의 마지막 인자 인 멤버 options에서 온다 hash. 이런 식으로 첫 번째 인수 (부분 이름)를 받고 그 이후의 데이터를 얻을 수 있습니다.

그런 다음 Handlebars.SafeString헬퍼에서 a를 반환 하거나 "triple-stash"를 사용 {{{하여 이중 이스케이프를 방지 할 수 있습니다.

다소 완전한 사용법 시나리오는 다음과 같습니다.

<script id="text-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="text" id="{{id}}"/>
</script>

<script id="checkbox-field" type="text/x-handlebars-template">
  <label for="{{id}}">{{label}}</label>
  <input type="checkbox" id="{{id}}"/>
</script>

<script id="form-template" type="text/x-handlebars-template">
  <form>
    <h1>{{title}}</h1>
    {{ render 'text-field' label="First name" id="author-first-name" }}
    {{ render 'text-field' label="Last name" id="author-last-name" }}
    {{ render 'text-field' label="Email" id="author-email" }}
    {{ render 'checkbox-field' label="Private?" id="private-question" }}
  </form>
</script>

이것이 누군가에게 도움이되기를 바랍니다. :)


15

자신의 도우미를 작성하면 매우 가능합니다. 우리는 $이러한 유형의 상호 작용을 달성하기 위해 맞춤형 도우미를 사용 하고 있습니다.

/*///////////////////////

Adds support for passing arguments to partials. Arguments are merged with 
the context for rendering only (non destructive). Use `:token` syntax to 
replace parts of the template path. Tokens are replace in order.

USAGE: {{$ 'path.to.partial' context=newContext foo='bar' }}
USAGE: {{$ 'path.:1.:2' replaceOne replaceTwo foo='bar' }}

///////////////////////////////*/

Handlebars.registerHelper('$', function(partial) {
    var values, opts, done, value, context;
    if (!partial) {
        console.error('No partial name given.');
    }
    values = Array.prototype.slice.call(arguments, 1);
    opts = values.pop();
    while (!done) {
        value = values.pop();
        if (value) {
            partial = partial.replace(/:[^\.]+/, value);
        }
        else {
            done = true;
        }
    }
    partial = Handlebars.partials[partial];
    if (!partial) {
        return '';
    }
    context = _.extend({}, opts.context||this, _.omit(opts, 'context', 'fn', 'inverse'));
    return new Handlebars.SafeString( partial(context) );
});

1
전달 된 인수에 액세스하려면 'hash'오브젝트 ({{hash.foo}})를 찾아야합니다. (나는 핸들 바를 처음 사용했고 이것을 알아내는 데 시간이 걸렸다.)-고마워, 훌륭한 도우미!
Claudio Bredfeldt

도우미를 사용하기 전에 부분 컴파일을 미리 컴파일해야합니다. node.js에서 Handlebars를 사용하고 있는데 이것이 항상 그런 것은 아니라는 것을 알았습니다 (부분은 요청시 컴파일되었습니다). 부분을로드 한 후 사전 컴파일을하기 위해 간단한 도우미를 추가해야했습니다.
Dan

@ 도우미를 공유 할 수 있습니까? :)
Tom

1
@Tom, 여기 있습니다 (멋지게 포맷하는 방법을 알 수 없습니다, 죄송합니다) : hbs.registerPartials(path.join(__dirname, '/views/partials'), function() { utils.precompileHandlebarsPartials(hbs); }); // Pre compile the partials precompileHandlebarsPartials : function(hbs) { var partials = hbs.handlebars.partials; for (var partial in partials) { if (typeof partials[partial] === 'string') { partials[partial] = hbs.handlebars.compile(partials[partial]); } }; }
Dan

@Dan 아마도 자체 답변으로 추가하는 것이 좋습니다.
alex

14

다음 key=value표기법을 사용하여 이후 버전의 핸들 바에서도 수행 할 수 있습니다 .

 {{> mypartial foo='bar' }}

특정 값을 부분 컨텍스트에 전달할 수 있습니다.

참조 : 부분 # 182와 다른 컨텍스트


1
이것은 v2.0.0 alpha 버전부터 사용할 수 있습니다
Kevin Borders

9

허용되는 답변은 부분적으로 다른 컨텍스트를 사용하려는 경우 효과적입니다. 그러나 부모 컨텍스트를 참조 할 수는 없습니다. 여러 인수를 전달하려면 자신의 도우미를 작성해야합니다. 다음은 Handlebars에 대한 작업 도우미입니다 2.0.0(다른 답변은 버전에 대해 작동 함 <2.0.0).

Handlebars.registerHelper('renderPartial', function(partialName, options) {
    if (!partialName) {
        console.error('No partial name given.');
        return '';
    }
    var partial = Handlebars.partials[partialName];
    if (!partial) {
        console.error('Couldnt find the compiled partial: ' + partialName);
        return '';
    }
    return new Handlebars.SafeString( partial(options.hash) );
});

그런 다음 템플릿에서 다음과 같은 작업을 수행 할 수 있습니다.

{{renderPartial 'myPartialName' foo=this bar=../bar}}

그리고 부분적으로 다음과 같은 컨텍스트로 해당 값에 액세스 할 수 있습니다.

<div id={{bar.id}}>{{foo}}</div>

Handlebars 1.0.0 으로이 버전을 사용해 보았으며 완벽하게 작동했습니다.
Christopher Lörken

이 부분에서 '...'부분에 대한 '검색'은 어디에 있습니까?
kemagezien

8

다음과 같이하고 싶은 것처럼 들립니다.

{{> person {another: 'attribute'} }}

Yehuda는 이미 그 방법을 제시했습니다.

{{> person this}}

그러나 명확히하기 위해 :

부분적으로 자체 데이터를 제공하려면 다음과 같이 기존 모델 내부에 자체 모델을 제공하십시오.

{{> person this.childContext}}

다시 말해, 이것이 모델에 제공하는 모델 인 경우 :

var model = {
    some : 'attribute'
}

그런 다음 부분에 부여 할 새 객체를 추가하십시오.

var model = {
    some : 'attribute',
    childContext : {
        'another' : 'attribute' // this goes to the child partial
    }
}

childContext점에서, 그것은 단지 현장을보고 - 예후 다 같은 부분의 맥락 말했다되고 another있지만, 볼 (또는 필드에 대한 상관하지 않는다 some). 당신이 있다면 id상위 레벨 모델에서, 반복 idchildContext 다시 부분은 안에 무엇이보고로, 그것은 잘 작동합니다 childContext.



1

이것이 도움이되는지 확실하지 않지만 다음은 동적 매개 변수가 인라인 RadioButtons 부분으로 전달되고 클라이언트 (브라우저)가 컨테이너에 라디오 버튼을 렌더링하는 Handlebars 템플릿의 예입니다.

내 사용을 위해 서버의 핸들 막대로 렌더링되어 클라이언트가 완료 할 수 있습니다. 이를 통해 양식 도구는 도우미없이 핸들 바 내에 인라인 데이터를 제공 할 수 있습니다.

참고 :이 예제에는 jQuery가 필요합니다

{{#*inline "RadioButtons"}}
{{name}} Buttons<hr>
<div id="key-{{{name}}}"></div>
<script>
  {{{buttons}}}.map((o)=>{
    $("#key-{{name}}").append($(''
      +'<button class="checkbox">'
      +'<input name="{{{name}}}" type="radio" value="'+o.value+'" />'+o.text
      +'</button>'
    ));
  });
  // A little test script
  $("#key-{{{name}}} .checkbox").on("click",function(){
      alert($("input",this).val());
  });
</script>
{{/inline}}
{{>RadioButtons name="Radio" buttons='[
 {value:1,text:"One"},
 {value:2,text:"Two"}, 
 {value:3,text:"Three"}]' 
}}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.