Handlebars.js: Bisakah saya menggunakan beberapa pembantu dalam satu tag?

Dibuat pada 7 Sep 2012  ·  17Komentar  ·  Sumber: handlebars-lang/handlebars.js

seperti {{ helper1 helper2 text }} , Anda tahu terkadang hanya satu pembantu saja tidak cukup untuk melakukan pekerjaan itu.

Komentar yang paling membantu

ini tampaknya memiliki dukungan asli menggunakan sesuatu seperti:

{{ helper1 (helper2 text) }}

Semua 17 komentar

Saya pikir perlu ada cara untuk menyarangkan ekspresi, seperti ini: {{headerText {{getTitle "my_page"}}}} .

Itu saat ini tidak didukung dan saya tidak punya rencana untuk mendukungnya.

Namun, Anda secara teoritis dapat membuat pembantu yang dengan sengaja mengkonsumsi dan mengikat pembantu lain:

{{chain "helper1" "helper2" text}}

Jika seseorang tertarik, saya telah membuat pembantu seperti itu:

Handlebars.registerHelper('chain', function () {
    var helpers = [], value;
    $.each(arguments, function (i, arg) {
        if (Handlebars.helpers[arg]) {
            helpers.push(Handlebars.helpers[arg]);
        } else {
            value = arg;
            $.each(helpers, function (j, helper) {
                value = helper(value, arguments[i + 1]);
            });
            return false;
        }
    });
    return value;
});

Bekerja seperti ini:

{{chain "taxAdd" "formatPrice" this.product.price}}

@Znarkus yang memperkenalkan ketergantungan pada jQuery

@jrajan Saya hanya menggunakan jQuery.each , jangan ragu untuk menulis ulang dengan apa pun preferensi Anda.

Jika ada yang tertarik dengan versi agnostik jQuery:

Handlebars.registerHelper('chain', function() {
  var helpers = [];
  var args = Array.prototype.slice.call(arguments);
  var argsLength = args.length;
  var index;
  var arg;

  for (index = 0, arg = args[index];
       index < argsLength;
       arg = args[++index]) {
    if (Handlebars.helpers[arg]) {
      helpers.push(Handlebars.helpers[arg]);
    } else {
      args = args.slice(index);
      break;
    }
  }

  while (helpers.length) {
    args = [helpers.pop().apply(Handlebars.helpers, args)];
  }

  return args.shift();
});

Satu masalah dengan kedua implementasi perlu diperhatikan: jika ada argumen yang dimaksudkan sebagai nilai yang akan diteruskan ke helper, tetapi juga merupakan string (dipaksa) yang cocok dengan nama helper yang ada, akan ada hasil yang tidak diharapkan.

Berikut dua implementasi. Keduanya memungkinkan Anda untuk mengirim beberapa argumen ke setiap pembantu, tidak seperti contoh sebelumnya.
Mereka juga ditulis dalam skrip kopi dan bergantung pada garis bawah atau lodash.

Yang pertama memungkinkan Anda melakukan sesuatu seperti ini:
{{{chain 'join-strings' 'link-twitter-handles' '@' twitterUsername}}}
Tetapi sesuatu seperti ini akan menghasilkan hasil yang tidak terduga:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}

Handlebars.registerHelper 'chain', ->
    # Get rid of the options hash
    args = Array.prototype.slice.call arguments, 0, -1
    helpers = []
    argsForHelpers = null
    value = undefined

    _.each args, (arg, i) ->
        if Handlebars.helpers[arg]
            helpers.push Handlebars.helpers[arg]
        else if not value # Only call the helpers once
            value = arg
            unless argsForHelpers
                argsForHelpers = args[i+1..-1]
                argsForHelpers.unshift value
            _.each helpers, (helper) ->
                argsForHelpers[0] = value
                value = helper.apply null, argsForHelpers

    value

Contoh kedua ini memiliki pemisah yang memungkinkan chain memisahkan helper dari argumen.
Pembantu akan menganggap bahwa setiap argumen sebelum pemisah adalah pembantu dan semua yang lain harus diteruskan sebagai argumen kepada pembantu.

Handlebars.registerHelper 'chain', ->
    # Get rid of the options hash
    args = Array.prototype.slice.call arguments, 0, -1
    helpers = []

    for arg,i in args
        if arg is '--'
            argsForHelpers = args.slice i + 1
            value = argsForHelpers[0]
            break
        else
            helpers.push Handlebars.helpers[arg]

    _.each helpers, (helper) ->
        argsForHelpers[0] = value
        value = helper.apply null, argsForHelpers

    value

Mengingat templat ini:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
dan objek ini:
{twitterUsername: 'abc'}
Kita bisa mengharapkan template yang dikompilasi seperti ini:
<a href="https://twitter.com/join-stringsabc">@join-stringsabc</a>

Saya telah mengambil implementasi @cdata dan mengubahnya menjadi versi untuk pembantu blok. Saya juga mengharuskan nama pembantu diawali dengan '!!' untuk menghindari masalah argumen yang cocok dengan nama pembantu.

/**
 * Takes an arbitrary number of arguments, the first of which is the operation type 'AND' or 'OR'.
 * Following that will be a list of block helper names prefixed by '!!'.
 * Calls each block helper with the remaining arguments.
 *
 * <strong i="7">@returns</strong> {string}  returns options.fn(this) or options.inverse(this) depending on result of each helper and operation type
 */
Handlebars.registerHelper('chainBlockHelpers', function() {
    var index, arg, helperResult, pass,
        helpers = [],
        args = Array.prototype.slice.call(arguments),
        argsLength = args.length,
        options = args[argsLength-1],
        operation = args.shift(),
        passVal = options.fn(this),
        failVal = options.inverse(this);

    if (operation !== 'AND' && operation !== 'OR')
        throw new Error ('chainBlockHelpers only supports "AND" or "OR" operations.')

    for (index = 0, arg = args[index]; index < argsLength; arg = args[++index]) {
        if (typeof arg == 'string' && arg.startsWith('!!') && Handlebars.helpers[arg.substr(2)]) {
            helpers.push(Handlebars.helpers[arg.substr(2)]);
        } else {
            args = args.slice(index);
            break;
        }
    }

    if (operation === 'AND') {
        pass = true;
        while (helpers.length) {
            helperResult = helpers.pop().apply(Handlebars.helpers, args);
            if (helperResult == failVal) {
                pass = false;
                break;
            }
        }
    } else {
        pass = false;
        while (helpers.length) {
            helperResult = helpers.pop().apply(Handlebars.helpers, args);
            if (helperResult == passVal) {
                pass = true;
                break;
            }
        }
    }

    return pass ? passVal : failVal;
});

ini tampaknya memiliki dukungan asli menggunakan sesuatu seperti:

{{ helper1 (helper2 text) }}

Dalam beberapa kasus, Anda dapat membuat pembantu Anda bekerja seperti:

{{#helper1}}{{helper2}}content{{/helper2}}{{/helper1}}

@Znarkus Menggunakan metode Anda, ketika saya

    Handlebars.registerHelper('shortNumber', function (value) {
        //return new Handlebars.SafeString(iSpot.number.shortNumber(value)); // Breaks
        return iSpot.number.shortNumber(value);  // Works
    });
    Handlebars.registerHelper('asDollars', function (value) {
        //return new Handlebars.SafeString(iSpot.number.asDollars(value)); // Breaks
        return iSpot.number.asDollars(value); // Works
    });

+1 pendekatan @amwmedia - {{pluralize (titleize (humanize schema.name))}}

+1 yang terlihat seperti sintaks bersih yang bagus.

+1 @amwmedia Berfungsi dengan baik, terima kasih

@breandr / @amwmedia pendekatan bekerja seperti Handlebars.SafeString() seperti @cssagogo disebutkan di atas.

Jadi Anda bisa melakukan sesuatu. Suka:

{{> partial text=(concat value (default extension 'PDF')) }}

Terima kasih

Saya sendiri mengalami masalah ini. Saya tahu saya sangat terlambat dalam hal ini, tetapi saya memiliki solusi yang berhasil untuk saya. Mohon maafkan saya jika ini sudah disebutkan (saya tidak meluangkan waktu untuk memeriksa). Ini bukan solusi paling keren dan secara teknis bukan jawaban langsung untuk pertanyaan Anda tetapi ini adalah solusi untuk masalah (menjalankan banyak fungsi pada satu nilai).

Saya menyimpan semua fungsi pembantu saya dalam file terpisah. Karena semuanya berada di tempat yang sama, saya dapat meneruskan nilainya ke satu pembantu dan kemudian memanggil fungsi lain apa pun yang saya miliki di file fungsi pembantu saya. Jadi:

{{ function1 value }}

berkas pembantu

function2 (value) {
   // code
}

function1 (value) {
   // code
   function2(value)
   // code
   return value;
}

Tentu saja, ini adalah cara sederhana untuk dapat menggunakan fungsi sebanyak yang Anda inginkan. Anda bahkan dapat menetapkan fungsi dasar yang bertindak sebagai "perantai" Anda.

{{ chainer value }}

berkas pembantu

function1 (value) {
   // code
}
function2 (value) {
   // code
}
function3 (value) {
   // code
}
function4 (value) {
   // code
}

function chainer(value) {
   function1(value)
   function2(value)
   function3(value)
   function4(value)
   return value;
}

Saya belum melakukan ini sendiri tetapi saya tidak melihat mengapa itu tidak berhasil.

Catatan Anda hanya perlu mendaftarkan fungsi yang ingin Anda gunakan di html Anda sebagai pembantu setang. Saya pribadi memiliki semua milik saya yang terdaftar karena saya menggunakannya secara independen satu sama lain, tetapi Anda tidak perlu melakukannya jika Anda tidak melihat diri Anda perlu menggunakannya secara langsung.

Kemunduran ke pemrograman prosedural :)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat